2013-03-31 54 views
0
#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它initiailized之前被使用。我的问题是做这件事的'正确'是什么。

+0

@zneak一个简单MWE将使用户建议只是“重新排序的成员。” – aiao

+0

据我所知,你只需要一个需要用成员字段进行初始化的基类。 – zneak

回答

2

这是一种情况,其中设计,而不是代码需要固定。

通过自己的设计:

  • 一个BarChild必须FooParent之前建造。
  • A FooParent必须在FooChild之前构建。
  • A FooChild必须在BarChild之前构建。

如果你想同时FooParentFooChild指此相同的酒吧对象 - 因为你试图在你的代码 - 设计父类来管理它。

一个例子的解决方案:

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不需要自己的这个对象的实例。

+0

>通过您自己的设计: > > BarChild必须在FooParent之前构建。一个FooParent必须是在FooChild之前构建的 >。 FooChild必须在BarChild之前构建。 我编辑了这个问题来反映我的意图。如果可能,我不想使用堆。请指教。 – aiao

+0

@aiao如果您有新问题,您应该发布一个新问题。这不是一个有效的来回讨论的论坛。祝你好运! –

0

尊重初始化的顺序。

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

是否有任何理由不能让barChild(在FooChild中)指针呢?

+0

是的,我需要'BarChild'来驻留'FooChild'。否则,我会有一个肮脏的架构 – aiao

+0

你是什么意思的“脏”的架构? – maditya

+0

您目前的实施也不干净。您的基类中有一个指向派生类中的成员的指针,这非常奇怪。 – maditya

0

我认为你将不得不寻找另外一个例子:这个人是因为这是不强制执行RAIII原则错误:FooParent持有它不控制值的指针。该设置失败的一个有趣例子是slicing problem

0

快速和肮脏的解决方案:

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