我正在尝试理解当从构造函数调用要重写的方法时方法覆盖是如何工作的。
(使用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()
?
我目前使用的替代方法是从::Initialize()
构造函数中删除Foo
,并执行以下操作:
Bar bar;
bar.Initialize();
并将Bar::Initialize()
修改为
void Bar::Initialize() override {
Foo::Initialize();
///... bar-specific initialization here
}
这是最佳或唯一的方法吗?
答案 0 :(得分:4)
很抱歉,您无法执行此操作,因为Foo
构造函数正在运行时,您有一个Foo
而不是Bar
。在Bar
构造函数运行之前,Bar
的覆盖都不可用。
子类在超类构造期间的控制级别是通过初始化机制调用哪个超类构造函数以及它获取的参数。
顺便说一句,如果它像你期望的那样工作,你的输出实际上是:Creating Bar
Foo::Foo()
Bar::Initialize()
Bar::Bar()