请告诉我为什么虚函数在以下代码中不起作用

时间:2015-02-27 18:16:50

标签: c++ oop polymorphism virtual-functions

当我运行此代码时,由于我们在基类使用了虚函数,因为后期绑定,输出正如预期的“这是派生2”。

    #include <iostream>
    using namespace std;

    class  Base {
        public :
        virtual void show() {
            cout<<"This is base class"<<endl;
        }
    };
    class  Derived : public Base {
        public:
        void show() {
            cout<<"This is derived class"<<endl;
        }
    };

    class D2 : public Derived {
        public :
        void show () {
            cout<<"This is derived 2"<<endl;
        }
    };

    int main() {
        Base *obj = new D2();
        obj->show();
        return 0;
    }

同样,如果我将代码更改为

        #include <iostream>
        using namespace std;

        class  Base {
            public :
             void show() {
                cout<<"This is base class"<<endl;
            }
        };
        class  Derived : public Base {
            public:
            virtual void show() {
                cout<<"This is derived class"<<endl;
            }
        };

        class D2 : public Derived {
            public :
            void show () {
                cout<<"This is derived 2"<<endl;
            }
        };

        int main() {
            // your code goes here
            Derived *obj = new D2();
            obj->show();
            return 0;
        }

同样的事情发生了,虚函数在基类中定义,在这种情况下是“Derived”类,Pointer也是“Derived”类型,所以再次调用show()给我最大的派生版本。

但我无法理解在“Derived”类中定义虚函数时发生了什么,并且我使用了类“Base”的基指针。以下代码的输出

    #include <iostream>
    using namespace std;

    class  Base {
        public :
         void show() {
            cout<<"This is base class"<<endl;
        }
    };
    class  Derived : public Base {
        public:
        virtual void show() {
            cout<<"This is derived class"<<endl;
        }
    };

    class D2 : public Derived {
        public :
        void show () {
            cout<<"This is derived 2"<<endl;
        }
    };

    int main() {
        // your code goes here
        Base *obj = new D2();
        obj->show();
        return 0;
    }

输出:“这是基类”。请帮我理解这个输出。

3 个答案:

答案 0 :(得分:4)

您的上一个代码段不起作用的原因是void show()函数仅在派生类中为virtual,但在基类中不在。如果从Derived派生的任何类将覆盖它,然后通过指向Derived的指针调用它,您将看到多态行为。但是,通过基指针调用的方式是非虚拟的,因此会调度到Base的实现。

您可以通过在基类中声明show virtual来解决此问题:

class  Base {
    public :
    virtual void show() {
//  ^^^^^^^
        cout<<"This is base class"<<endl;
    }
};

Demo 1

或通过指向D2

的指针访问Derived
Derived *obj = new D2();
obj->show();

Demo 2

答案 1 :(得分:0)

在最后一个示例中,D2Base*,因此该类是否派生并不重要。

如果您已将obj指向DerivedD2,则结果会有所不同。

答案 2 :(得分:0)

对象的静态类型objBase *

Base *obj = new D2();

因此编译器只能调用此类中声明的成员函数。在类Base函数show不是虚拟的。所以它在编译时被编译器选中。基类对在派生类中声明的虚函数一无所知。在您的示例中,基类甚至没有虚函数的地址表,因为类中的函数都没有声明为虚函数。

派生类的虚函数将被称为派生类,应将基类虚函数的地址替换为基类中虚函数地址表中其自身函数的地址。