【问题标题】:C++ Inheritance - calling overrides from constructor [duplicate]C ++继承 - 从构造函数调用覆盖[重复]
【发布时间】:2014-02-17 13:44:05
【问题描述】:

我试图了解当从构造函数调用要被覆盖的方法时,方法覆盖是如何工作的。

(使用VS2012)

给定测试程序:

#include <string>
#include <iostream>

using namespace std;

struct Foo
{
    Foo()
    {
        cout << "\tFoo::Foo()" << endl;
        Initialize();
    }

    virtual void Initialize()
    {
        cout << "\tFoo::Initialize()" << endl;
    }

};

struct Bar : public Foo
{
    Bar()  { 
        cout << "\tBar::Bar()" << endl; 
    } 

    void Initialize() override
    {
        cout << "\tBar::Initialize()" << endl;
    }
};


int main(int argc, char *argv[])
{
    cout << "Creating Foo" << endl;

    Foo foo;

    cout << endl;

    cout << "Creating Bar" << endl;

    Bar bar;

    std::getchar();

    return 0;
}

我得到以下输出:

Creating Foo
        Foo::Foo()
        Foo::Initialize()

Creating Bar
        Foo::Foo()
        Foo::Initialize()
        Bar::Bar()

我希望第二部分是:

Creating Bar
    Foo::Foo()
    Foo::Initialize()
    Bar::Initialize()   <---- Not called.
    Bar::Bar()

我希望,当调用 Foo ctor 并调用 ::Initialize() 时,实际上会调用覆盖 Bar::Initialize()

现在,我可以猜到为什么会发生这种情况了:当Foo::Foo() 被调用时,在Bar::Bar() 的主体被执行之前,并不能保证Bar::Initialize() 需要的项目已经被分配,更不用说初始化了。

问题

我能否覆盖由基构造函数调用的方法,并在实例化派生类时执行该覆盖?也就是有什么办法可以修改上面的代码,让Bar::Initialize()被调用?

我目前使用的替代方法是从 Foo 构造函数中删除 ::Initialize(),然后执行以下操作:

Bar bar;
bar.Initialize();

并将Bar::Initialize()修改为

void Bar::Initialize() override {
Foo::Initialize();
///... bar-specific initialization here
}

这是最好的还是唯一的方法?

【问题讨论】:

    标签: c++ inheritance c++11 overriding


    【解决方案1】:

    抱歉,您不能这样做,因为当 Foo 构造函数正在运行时,您有一个 Foo 而不是 Bar。在Bar 构造函数运行之前,Bar 的任何覆盖都不可用。

    子类在超类构造过程中的控制级别是通过初始化机制调用哪个超类构造函数以及它获取哪些参数。

    顺便说一句,如果它像您预期的那样工作,您的输出实际上是:

    Creating Bar
        Foo::Foo()
        Bar::Initialize()
        Bar::Bar()
    

    【讨论】:

    • 这就是我所期望的。那么,这意味着每次我需要这些东西之一时,我都会被单独的实例化后的 Initialize() 调用所困扰? (这几乎不是什么不便,但似乎很像在整个地方重复自己。)
    • 我不确定你是否需要Initialize。如果您只是在Foo 构造函数的末尾调用Initialize,只需将该代码放入Bar 构造函数中即可。
    • 这是有道理的。导致这种模式的情况有点奇怪。猜猜是时候进行一些重构了。
    • 真正的问题是为什么你觉得有必要这样做......
    • 有多个构造函数,每个构造函数执行一些相同的初始化。而不是必须在每个派生类中显式调用 ::Initialize() (这是我放置初始化代码的地方,而不是在每个构造函数中剪切和粘贴),我想我会从基本构造函数中调用它。就像我说的,为什么这不起作用是有道理的——我只是想知道是否有更好的选择。 (请注意,我正在使用的 VS2012 不支持构造函数链接。)
    猜你喜欢
    • 1970-01-01
    • 2014-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-20
    • 2014-01-31
    • 2011-05-31
    相关资源
    最近更新 更多