这个子对象在构造之前不会被使用,只有它的指针会被存储。
考虑以下代码。
class Base1;
class Base0
{
public:
Base0(Base1* obj1) :
anotherObj(new AnotherClass(obj1)) // only saves the pointer, doesn't use the object
{}
AnotherClass* anotherObj;
};
class Base1 { /*...*/ };
class Derived : public Base0, public Base1
{
public:
Derived() :
Base0(this), // expecting an implicit conversion of Derived* to Base1*
Base1()
{}
};
能否在任何base的构造发生之前 把这个指针上传到任何一个base上 并得到一个有效的指针?还有更复杂的情况,比如虚拟继承呢?
一般来说,这是一种有点危险的模式。严格保持事物的有效性是可能的,但在所示的例子中,实际上是在从 Base1*
到 AnotherClass*
这是标准所不允许的。
[class.cdtor]2 给出了一些关于将一个指针从派生类转换到基类的限制。
要显式或隐式地将一个指针(glvalue)转换到一个类的对象上
X
到直接或间接基类的指针(引用)。B
的X
的建设。X
及其直接或间接衍生的所有直接或间接基础的建设。B
应已开始,并且这些类的销毁应未完成,否则转换将导致未定义的行为。
当初始化器"this
"为 Base0
子对象进行了评估,构建了 Derived
已经开始,但其建设 Base1
子对象还没有启动。但由于继承树中没有其他类派生自 Base1
జజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజ Derived*
到 Base1*
转换是可以的。转换 this
到一个指向祖父母类的指针,如果祖父母类的构造函数还没有开始的话,是不可以的;如果祖父母类是一个虚拟的基类,那么在继承它的最后一个中间类开始构造之前,是不允许进行转换的!如果祖父母类是一个虚拟的基类,那么转换后的指针会指向一个还没有开始构造的对象。
起初,那个转换后的指针指向一个对象,而这个对象的(非平凡的)构造还没有开始,所以它受到了在 [class.cdtor]1 和 [基本生活]6. 大多数情况下,你还不能接触到它的任何基类子对象或成员。复制那个指针,而不做任何进一步的隐式基类指针转换,几乎是你能合法地对它做的所有事情。所以本例中隐式转换从 Base1*
到 AnotherClass*
导致未定义的行为。不过,如果 anotherObj
的成员有完全相同的类型 Base1*
.