【问题标题】:C++ override inherited methodsC++ 覆盖继承的方法
【发布时间】:2016-01-25 19:31:40
【问题描述】:

我有以下两个课程。由于Child 继承自Father,我认为Child::init() 会覆盖Father::init()。为什么,当我运行程序时,我得到的是“我是父亲”而不是“我是孩子”?如何执行Child::init()

你可以在这里测试它:https://ideone.com/6jFCRm

#include <iostream>

using namespace std;

class Father {
    public:
        void start () {
            this->init();
        };

        void init () {
            cout << "I'm the father" << endl;
        };
};

class Child: public Father {
    void init () {
        cout << "I'm the child" << endl;
    };
};

int main (int argc, char** argv) {
    Child child;
    child.start();
}

【问题讨论】:

  • 您没有将init 函数设为虚拟(即virtual void init();)。
  • 因为init不是virtual,而start属于Father类所以它会调用那里定义的init
  • 孩子的init() 不会覆盖父亲的init() 基本上Child::start()Father::init()
  • 我很惊讶没有给出隐藏父方法的警告:(
  • 阴影不是值得警告的事情,因为有时这正是程序员想要的:/

标签: c++ oop c++11 inheritance


【解决方案1】:

当前Child::init隐藏 Father::init,而不是覆盖它。您的 init 成员函数需要为 virtual 才能获得动态调度:

virtual void init () {
    cout << "I'm the father" << endl;
};

或者,您可以将 Child::init 标记为 override 以明确表示您要覆盖虚函数(需要 C++11):

void init () override {
    cout << "I'm the child" << endl;
};

【讨论】:

  • 当没有虚拟时,由于没有后期绑定,因此在编译时计算为指向基类的指针,这是您的意思吗?因为如果它不是虚拟的,并且 init 是公共的,那么 child.init() 会打印 child。那么这个指针是这种行为的原因吗?
  • “override”关键字的另一个目的是让编译器检查并确保基类和派生类中的两个方法具有相同的签名。如果派生类中的方法使用了关键字“override”,但其签名与基类中的任何方法都不匹配,则编译器会报错。
【解决方案2】:

你应该用函数说明符virtual定义函数

例如

#include <iostream>

using namespace std;

class Father {
    public:
        virtual ~Father() {}

        void start () {
            this->init();
        };

        virtual void init () const {
            cout << "I'm the father" << endl;
        };
};

class Child: public Father {
    void init () const override {
        cout << "I'm the child" << endl;
    };
};

int main()
{
    Child child;
    child.start();

    return 0;
}

否则函数start 在其自身类的范围内搜索名称init。并且因为函数init 不是虚拟的,即它没有在派生类中被覆盖,所以基类函数init 被调用。

【讨论】:

  • 当没有 virtual 时,由于没有后期绑定,因此在编译时计算为指向基类的指针,这是您的意思吗?
【解决方案3】:

如果你想让孩子重写init方法,你必须在基类virtual中创建init方法。

class Father {
    public:
        void start () {
            this->init();
        };

        virtual void init () {
            cout << "I'm the father" << endl;
        };
};

重新声明和重新实现其基础之一的虚拟方法的类被称为覆盖该方法。为了对方法进行后期绑定,您需要声明该方法virtual

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-20
    • 2016-06-04
    • 1970-01-01
    • 2011-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-27
    相关资源
    最近更新 更多