【问题标题】:C++ - Dynamic Binding and Object Instances Not Accessing Derived MethodsC++ - 动态绑定和对象实例不访问派生方法
【发布时间】:2014-03-31 17:02:42
【问题描述】:

我已经有一段时间没有用 C++ 编写任何东西了,并且遇到了一些令人困惑的继承问题。

第一个问题 - 据我了解,如果从指向基类的指针调用该方法,则具有其派生类实现该方法的虚拟方法的基类应该调用派生方法。为什么它需要是一个指针?这是因为 vtables 的实现方式吗?如果是这样,为什么在实际规范中没有抽象出实现细节?我试图理解为什么会这样。只有当对象不是指针时,您是否希望调用基类?我认为重点在于指向对象的指针的行为与这些对象相似。

第二个问题 - 在下面的代码中,我运行了一个测试来查看如果访问方法是指针,则调用派生类方法。然后,我又回去尝试用同样的方法将实例变成指针来实现同样的绑定。但是,如果该类在任何时候都存储为对象实例,则没有任何强制转换允许我将该类用作派生类。为什么是这样?例如,如果我将相同的对象(下文详述)放入向量中,则它可以正常工作。

    #include <iostream>
    #include <string>
    #include <vector>
    using namespace std;

    class BaseClass {
    public:
        virtual void A();
        virtual void B();
    };

    void BaseClass::A() {
        cout << "In base A" << endl;
    }

    void BaseClass::B() {
        cout << "In base B" << endl;
    }

    class DerivedClass1 : public BaseClass {
    public:
        void A();
        void B();
    };

    void DerivedClass1::A() {
        cout << "In Derived A" << endl;    
    }

    void DerivedClass1::B() {
        cout << "In Derived B" << endl;
    }

    int main(int argc, char** argv) {    
        string cmd;
        BaseClass bc;
        DerivedClass1 dc1;    

        vector<BaseClass> list;
        list.push_back(bc);
        list.push_back(dc1);    

        cout << "Calling by " << endl;
        for(int i = 0; i < list.size(); i++) {  
            // There is no possible cast to BaseClass* that causes A or B to call the derived class
            (dynamic_cast<BaseClass*>(&list[i]))->A();
            (dynamic_cast<BaseClass*>(&list[i]))->B();
        }


        // However, the below code, although it stores the same addresses, etc. works fine.
        vector<BaseClass*> list_ptrs;    
        list_ptrs.push_back(&bc);
        list_ptrs.push_back(&dc1);    

        cout << "Outputting Pointers" << endl;
        for(int i = 0; i < list_ptrs.size(); i++) {    
            list_ptrs[i]->A();
            list_ptrs[i]->B();
        }

        getline(cin, cmd);
    }

对不起,如果我只是误解了一些非常基本的东西,但这似乎是动态绑定工作方式的不一致,我找不到合适的解释(所有谷歌返回都是试图访问基类方法的人。 ..)。

任何帮助将不胜感激, 谢谢, -亚历克斯

【问题讨论】:

    标签: c++ pointers dynamic binding casting


    【解决方案1】:

    这是错误的:

        BaseClass bc;
        DerivedClass1 dc1;    
    
        vector<BaseClass> list;
        list.push_back(bc);
        list.push_back(dc1);    
    

    您的向量只能存储 BaseClass 对象。尝试将 DerivedClass 填充到只能包含 BaseClass 对象的东西中称为object slicing,这是您不希望发生的。对象切片意味着——您正在“切片”DerivedClass 的属性,使其成为 BaseClass。

    要么有一个 BaseClass 指针向量,要么有两个单独的向量,一个是 BaseClass 对象,另一个是 DerivedClass 对象。

    vector<BaseClass*> theList;
    theList.push_back(&bc);
    theList.push_back(&dc1);
    

    您现在应该会看到虚函数按预期工作。

    【讨论】:

    • 这是有道理的。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2018-11-03
    • 2014-01-14
    • 2018-01-18
    • 1970-01-01
    • 1970-01-01
    • 2010-09-22
    • 1970-01-01
    • 2018-02-24
    相关资源
    最近更新 更多