当无法重新排序时,依赖成员初始化

Dependent member initialization, when reorder is not possible

本文关键字:依赖 初始化 成员 排序 新排序      更新时间:2023-10-16
#include <iostream>
class BarParent
{
    public:
        int x;
        virtual void fuz() = 0;
};
class BarChild : public BarParent
{
    public: 
        BarChild(int new_x){x = new_x;}
        virtual void fuz(){}
};
class FooParent
{
    public:
        BarParent* p_barPar;
        FooParent (BarChild* new_p_bar)
        {
            p_barPar = new_p_bar;
            std::cout << p_barPar->x << std::endl;
        }
};
class FooChild: public FooParent
{
    public:
        BarChild barChild;
        FooChild(int new_x):FooParent(&barChild), barChild(new_x){}
};
int main()
{   
    FooChild foo(60);
    BarChild bar(99);
    FooParent fooP(&bar);
}
输出:

-548726160 
99

我明白为什么我得到这个结果(未定义的行为),barChild在初始化之前被使用。我的问题是什么是"正确的"做处理这个

这种情况下需要修复的是设计,而不是代码

由你自己设计:

  • BarChild必须先于FooParent
  • FooParent必须在FooChild之前构建。
  • FooChild必须先于BarChild

当你想要FooParentFooChild都引用同一个Bar对象时——就像你在代码中尝试的那样——设计父类来管理它。

一个示例解决方案:

    FooParent (BarChild* new_p_bar)
    {
        if ( new_p_bar == NULL )
           new_p_bar = new BarChild;
        p_barPar = new_p_bar;
        std::cout << p_barPar->x << std::endl;
    }

这里,FooChild不需要它自己的这个对象的实例

尊重初始化的顺序。

可以在BarParent内部创建一个函数来设置指针p_barPar。在FooChild的构造函数中调用该函数。

是否有任何理由你不能使barChild(在FooChild)一个指针,以及?

我认为你将不得不找到另一个例子:这是错误的,因为RAIII原则没有强制执行:FooParent持有一个指针上的值,它不控制。这个设置失败的一个有趣的例子是切片问题。

快速解决方案:

class FooChild: private BarChild, public FooParent
{
public:
        FooChild(int new_x): BarChild(new_x), FooParent(this) {}
};