从派生 class 成员初始化基 class 引用

Initialization of a base class reference from a derived class member

我有两个 class,BaseDerivedDerived 使用自己的成员对象构造 Base,该成员对象继承自 Base::BaseChild.

struct Base
{
    struct BaseChild
    {
        int x = 5;
    };
    Base(BaseChild& c): baseData(c), constantVar(c.x) 
    {
       assert(constantVar == 5);
    }
    int getX() const {return baseData.x;}

private:
    const int constantVar;
    BaseChild& baseData;
};


struct Derived: public Base
{
    struct DerivedChild: public BaseChild
    {
        double y = 4.0;
    };
    Derived(): Base(data) {}

private:
    DerivedChild data;
};


Derived myObject;
assert(myObject.getX() == 5);

推理:我这样做是因为对于我的情况来说一切看起来都非常封装,我需要发送 Childs 来交换他们的内容(vectorshared_ptr, unique_ptr) 与其他 Childs,保持子内存地址,我仍然可以从基 class 访问 Child 对象,而不需要虚函数,这会降低我的应用程序性能。

问题:我读过另一个 post like this one,其中说明 Derived 成员在 [=13] 之前初始化=] 不可能。所以 constantVar 断言总是会失败。但是 getX() 在构造函数之后工作正常,我对构造函数结束后调用的这些函数很感兴趣。这样安全吗?还是这里有什么隐患?

Derived 的基础 class Base 在成员 data 之前构造。

因此,当您将对它的引用传递给 Base 的构造函数时,data 将不会被初始化。初始化将在该构造函数调用之后发生。

然而,您正试图在 Base 的构造函数中读取 data 的成员 x。此时 data 的生命周期尚未开始,在其生命周期之外访问对象的 non-static 数据成员的值会导致未定义的行为。

断言是否成功并不重要。未定义的行为允许任何一种结果。

如果您不尝试在 Base 的构造函数中访问 data 的值,而只是存储引用,情况可能会有所不同(尽管从技术上讲不是标准中的规则)