在对象构造过程中,将一个尚未构造的子对象的指针传递给另一个子对象的构造函数,是否有危险?

问题描述 投票:0回答:1

这个子对象在构造之前不会被使用,只有它的指针会被存储。

考虑以下代码。

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上 并得到一个有效的指针?还有更复杂的情况,比如虚拟继承呢?

c++ inheritance constructor type-conversion this
1个回答
1
投票

一般来说,这是一种有点危险的模式。严格保持事物的有效性是可能的,但在所示的例子中,实际上是在从 Base1*AnotherClass* 这是标准所不允许的。

[class.cdtor]2 给出了一些关于将一个指针从派生类转换到基类的限制。

要显式或隐式地将一个指针(glvalue)转换到一个类的对象上 X 到直接或间接基类的指针(引用)。BX的建设。X 及其直接或间接衍生的所有直接或间接基础的建设。B 应已开始,并且这些类的销毁应未完成,否则转换将导致未定义的行为。

当初始化器"this"为 Base0 子对象进行了评估,构建了 Derived 已经开始,但其建设 Base1 子对象还没有启动。但由于继承树中没有其他类派生自 Base1జజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజ Derived*Base1* 转换是可以的。转换 this 到一个指向祖父母类的指针,如果祖父母类的构造函数还没有开始的话,是不可以的;如果祖父母类是一个虚拟的基类,那么在继承它的最后一个中间类开始构造之前,是不允许进行转换的!如果祖父母类是一个虚拟的基类,那么转换后的指针会指向一个还没有开始构造的对象。

起初,那个转换后的指针指向一个对象,而这个对象的(非平凡的)构造还没有开始,所以它受到了在 [class.cdtor]1[基本生活]6. 大多数情况下,你还不能接触到它的任何基类子对象或成员。复制那个指针,而不做任何进一步的隐式基类指针转换,几乎是你能合法地对它做的所有事情。所以本例中隐式转换从 Base1*AnotherClass* 导致未定义的行为。不过,如果 anotherObj 的成员有完全相同的类型 Base1*.

© www.soinside.com 2019 - 2024. All rights reserved.