【问题标题】:Please tell me why virtual function is not working in the following code请告诉我为什么虚拟功能在以下代码中不起作用
【发布时间】:2015-04-30 13:21:23
【问题描述】:

当我运行这段代码时,由于我们在基类中使用了虚函数,所以由于后期绑定,输出如预期的那样“这是派生的 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;
        }

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

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

    #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;
    }

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

【问题讨论】:

  • 你有一个基类指针,在基类show不是虚拟的。所以它当然是调用基类一。
  • @Borgleader 是的,但是我已经在 Derived 类中定义了虚函数,并且 D2 是从 Derived 派生的。它不应该从 D2 调用 show 吗?
  • 否,因为指针的静态类型是 Base 并且在 base 中函数不是虚拟的,所以它知道它可以在编译时解析调用,指针指向的对象的运行时类型确实没关系。
  • 不清楚您的问题/问题是什么。输出正是人们所期望的。也许您应该阅读virtual 函数和多态性的工作原理。您不能从派生的基础中继承。 virtual 函数不会覆盖基中匹配的 virtual 函数,只会影响 Derived* 的使用。

标签: c++ oop polymorphism virtual-functions


【解决方案1】:

对象obj的静态类型为Base *

Base *obj = new D2();

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

派生类的虚函数称为派生类,应在基类的虚函数地址表中用基类虚函数的地址代替其自身函数的地址。

【讨论】:

    【解决方案2】:

    您最后一个 sn-p 不起作用的原因是 void show() 函数仅在您的派生类中是 virtual,而不是在基类中。如果派生自Derived 的任何类将覆盖它,然后您通过指向Derived 的指针调用它,您将看到多态行为。但是,您这样做的方式是,通过基指针的调用是非虚拟的,因此它被分派到 Base 的实现。

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

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

    Demo 1

    或者通过指向Derived的指针访问D2

    Derived *obj = new D2();
    obj->show();
    

    Demo 2

    【讨论】:

      【解决方案3】:

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

      如果您将obj 设为指向DerivedD2 的指针,结果会有所不同。

      【讨论】:

        猜你喜欢
        • 2023-03-24
        • 2019-02-15
        • 2019-09-14
        • 2016-12-26
        • 2021-06-23
        • 2013-02-08
        • 2015-09-12
        • 1970-01-01
        • 2019-11-04
        相关资源
        最近更新 更多