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

3
我有两个类,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);
推理: 我这样做是因为在我的情况下,一切似乎都非常封装,我需要发送儿童来交换他们的内容(vector, shared_ptr, unique_ptr),保留子内存地址,并且我仍然可以从基类访问Child对象而无需虚函数,这提高了我的应用程序性能。 问题: 我读过另一篇帖子 像这样一个, 其中它声明在Base之前初始化Derived成员是不可能的。所以constantVar断言将始终失败。但是getX()在构造函数之后正常工作,我对这些函数很感兴趣,它们在构造函数结束后被调用。这安全吗?还是这里有隐藏的危险?

你是否同意在构造函数中删除所有读取/写入派生类数据的尝试(并将该功能推入成员函数中)?如果是,我认为我们可以通过CRTP实现你想要的。 - AndyG
是的,我可以接受这个。但是我不确定是否存在另一种未定义行为的风险,即使我在构造函数中没有读写。 - Juan JuezSarmiento
1个回答

4
Derived的基类Base在成员data之前构建。
因此,当您将对其的引用传递给Base的构造函数时,data将不会被初始化。初始化将在那个构造函数调用之后发生。
然而,您正在尝试在Base的构造函数中读取data的成员x。此时,data的生命周期尚未开始,访问对象生命周期外部的非静态数据成员的值会导致未定义行为。
无论断言是否成功都不重要。未定义行为可以允许任一结果。
如果您不是在Base的构造函数中尝试访问data的值,而仅存储对它的引用,则情况可能会有所不同(虽然在技术上不符合标准)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接