2015-11-30 56 views
1

基本上對象被創建之前,我已經擁有另一個對象一類:調用函數的一類

class A() 
{ 
    A() { initSystems() }; 
    void initSystems(); 
    B b; 
} 

class B() 
{ 
    B() { //Does stuff that requires 'initSystems()' to be called before } 
} 

和「B」到功能,在init系統功能需要A.被稱爲是有什麼「好」的方法來解決這個問題?像稍後創建'B'對象或什麼?

回答

4

聽起來像你的班級太tightly coupled。有很多方法可以解決這個問題,但這取決於您的其他設計。

也許A不應該擁有一個B,因爲A是B的依賴關係。當它們被實例化時,你可以在每個B中包含一個A的實例inject

也許乙不應該存在,所有,應該合併成一個:

class A() 
{ 
    A() { 
     initSystems(); 
     //Does stuff that requires 'initSystems()' to be called before 
    } 
    void initSystems(); 
    // B's methods 
} 

這是我認爲最初始化方法是代碼味道(即,它表明一個不好的設計)。有人給出了這個模式的名字:"Design Smell: Temporal Coupling"

1

你只需要改變你的設計,所以initSystems()是需要AB

如果你不能做到這一點(雖然你真的應該),還有其他的方法,如動態分配:

class A() 
{ 
    A() { 
     initSystems(); 
     b = std::make_unique<B>(); 
    }; 
    void initSystems(); 
    std::unique_ptr<B> b; 
} 
3

如果您希望保留B A的正式成員,這兩個地方你可以的b施工前運行代碼是:

  1. 一個基類的構造函數,在A的一個成員的初始化列表
  2. ,上面b聲明的成員。

如果您希望推遲構建B,您需要間接保持對象或稍後將其構建到原始存儲上,並在銷燬時執行佈局銷燬。

這其中大部分都有奇怪的氣味,重組你的代碼以避免這種結構可能是有益的。

+0

謝謝你的答覆,所以這將是保存一個指向B類,(B * B)是一個好主意,然後初始化後,我已經叫initSystems()在構造函數(b = new b();)中,還是應該重新設計我的類? (在現實中,A類是一個'遊戲'類,它實際上是第一個運行的類,而B類是一個將遊戲對象渲染到屏幕上的渲染類) – TheInfernalCow

+0

@ TheInfernalCow如果你的遊戲基本上是單一實例,希望將粘合劑和託管責任從其中移除到意識到系統和嵌套實體的事物上。它似乎是負責任的方式。 –

0

我同意@nanny關於類的解耦和如果可能的話合併。

但是你的情況似乎是在你的系統中B是獨立的實體,因此是一個類。並且A包含B,因此組成。

所以解決,這將是一個方法,你保持一個參考(指針)到B A的反而讓乙A.

的一部分,或者你不應該訪問在InitInstance中創建的東西( )的A,並在B中創建一個方法postConstruct,你可以在調用initInstance之後調用A方法。下面的代碼說明它,

class A() 
{ 
    A() 
    { 
     initSystems(); 
     b.postContruct() 
    } 
    void initSystems() 
    { 
     // do the init instance stuff here. 
    } 
    B b; 
} 

class B() 
{ 
    B() {} 

    void postContruct() 
    { 
     //Does stuff that requires 'initSystems()' to be called before 
    } 
}