2013-03-31 52 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) {} 
};