这是我本来想写的代码:
class A {
public:
A(someType someData) {
this->init(someData);
}
virtual void init(someType) = 0;
}
这是不允许的,因为当调用基类构造函数时,派生类的实例还不存在。所以我把它改成这样:
class A {
public:
A(someType someData, A* derived) {
derived->init(someData);
}
virtual void init(someType) = 0;
}
class B : public A {
public:
B(someType someData)
: A(someData, this) {}
}
代码编译并运行没有崩溃,但这是允许的还是UB?
class A {
public:
A(someType someData, A* derived) {
derived->init(someData);
}
virtual void init(someType) = 0;
};
class B : public A {
public:
B(someType someData)
: A(someData, this) {}
};
我的理解是,
B
的构造函数当然可以加载this
并将其传递给A
的构造函数...但是,在进入B
的构造函数的函数体之前,this
指针仍然仅指向 A
对象。 (事实上,在进入A
的构造函数体之前,它甚至还不会指向A
!)
因此,当您在
derived->init()
上调用 A* derived
时,derived
指向 A
-that-is-not-yet-a-B
。特别是,它仍然有A
的vptr,指向A
的vtable,其中A::init
是纯虚拟的。它不知道应该调用 B::init
。所以你调用了一个纯虚函数,即 UB - 实际上只会中止程序。
事实上,您可以尝试一下并亲自查看,甚至无需询问 StackOverflow。 :) 上帝之箭。