当无法重新排序时,从属成员初始化

时间:2013-03-31 20:24:46

标签: c++ pointers initialization

#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在它被初始化之前使用。我的问题是处理这个问题的“正确”是什么。

4 个答案:

答案 0 :(得分:2)

这是需要修复 design 而不是代码的情况。

按照你自己的设计:

  • 必须在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不需要自己的此对象实例。

答案 1 :(得分:0)

尊重初始化顺序。

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

你有什么理由不能让barChild(在FooChild中)成为一个指针吗?

答案 2 :(得分:0)

我认为你必须找到另一个例子:这个是错误的,因为RAIII原则没有强制执行:FooParent持有一个它不能控制的值的指针。此设置失败的一个有趣示例是slicing problem

答案 3 :(得分:0)

快速而肮脏的解决方案:

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