2009-11-10 32 views
4

我有這樣的定義在頭文件:在C++中初始化另一個類中的類?

class Owner 
{ 
private: 
    // Fields 
    Child* _myChild1; 
public: 
    // Constructors 
    Owner(); 
    Owner(const char childName[]); 
}; 

實施這一項目:

Owner::Owner(const char childName[]) 
{ 
//do some operations - children must be created after these ops 
_myChild = new Child(childName); 
} 

這個main()函數:

int main() 
{ 
Owner("child1"); 
} 

一些問題,並請包涵我在這裏,我剛剛開始用C++ ..

  • 鑑於子類在編譯時已知,我是否認爲我不需要在堆上使用'new'來創建它們?如果是這樣如何?我一直在使用這種語法在所有者實施,但編譯器呻吟嘗試(「術語不計算爲函數..」):

_myChild(childName);

  • 然而,在執行使用這種語法好吧,爲什麼?

Child _myChild(childName);

  • 是,我用正確的範式?換句話說,作爲一般規則,如果一個類包裝另一個類,那麼所有者只持有指向它所包裝的類的指針?
  • 你會如何更有經驗的人做到這一點?

感謝您的任何建議..

+0

在孩子創建之前需要做什麼操作?爲什麼? – 2009-11-10 22:45:27

回答

3

基本上,它的工作原理是這樣的:

  • 如果兒童類的之前完全定義所有者類,它可以全部包含在所有者中,或者作爲指針,無論您喜歡哪一個。
  • 如果子類類未在所有者類之前完全定義,則它必須是前向聲明的,並且只能作爲指針包含。這將不得不在new的堆上進行分配。

如果您確實包含完整的類,則將在構建所有者對象的同時構建它。除非另有明確說明,否則編譯器將爲此使用默認構造函數。

選項1:

// will create a Child object using the default constructor. 
// this is done even before doStuff() is called. 

Owner::Owner(const char childName[]) { 
    doStuff(); 
} 

選項2:

// will create a Child object using the Child(const char*) constructor. 
// again, done before doStuff() is called. 
Owner::Owner(const char childName[]): _myChild(childName) { 
    doStuff() 
} 

您不能使用構造函數本身內部的_myChild(childName);語法,因爲_myChild之前已經構建它有那麼多。 Child _myChild(childName);是合法的,但它會創建一個新的本地對象名爲_myChild而不是修改類成員_myChild。這可能不是預期的結果。

如果你想一個新的值賦給_myChild它建成後,執行下列操作之一:

  • 首選方法:修改現有的對象以某種方式(如重載賦值運算符允許你要做_myChild = childName;,或者使用某種形式的_myChild.setName(childName);函數)。
  • 替代方法:使用_myChild = Child(childName);創建新的並將其分配給成員變量。

第二個選項雖然功能強大,但效率低下,因爲它需要兩次構建對象,因爲沒有很好的理由。

+0

謝謝黃金,這是我一直在尋找的信息:) – jamieQ 2009-11-11 09:25:18

4

什麼你之類的描述這裏是「成分」,其中一類存在於另一個類。這裏,Owner包含指針Child。所以Child實例的實際分配和初始化必須在運行時進行。

如果你想Owner包含一個Child,你不必在堆上分配與new的一個實例,簡單地宣佈該成員變量爲:

Child _myChild1; 

,而不是作爲一個指針。

5

像這樣:

class Owner 
{ 
    private:  // Fields 
     Child _myChild1; 
    public:  // Constructors 
     Owner(); 
     Owner(const char childName[]); 
}; 

Owner::Owner() 
    :_myChild1("Default Name") 
{} 

Owner::Owner(const char childName[]) 
    :_myChild1(childName) 
{} 

// Without more info about what you are doing it is hard to tell 
// But a trivial change could be 

Owner::Owner() 
// Child defautl constructor called here 
{ 
    // Do processing. 
    _myChild1.updateName(name); 
} 

Owner::Owner(const char childName[]) 
// Child defautl constructor called here 
{ 
    // Do processing. 
    _myChild1.updateName(std::string("X") + childName); 
} 

的問題是,什麼樣的處理你所需要的孩子之前完成。

作爲一個邊不:

  • 避免強調如在構件名稱的第一個字符。
    大部分時間沒問題,但有些地方沒有。所以最好避免它們。
  • 而不是傳遞字符數組傳遞的std :: string常量&
+0

小錯字,該字段名爲_myChild1 – Rickard 2009-11-10 22:44:38

+0

ok,所以代碼比我提出的更復雜。我必須解析名稱和一些其他參數,然後將這些參數傳遞給正確的子項(有多個實例),因此我不能使用':_instance(args)'構造,初始化必須在正文中完成。鑑於此,我應該如何處理它?並感謝您的建議。 – jamieQ 2009-11-10 22:50:29

+0

您需要在問題中添加更多信息以獲得良好迴應。有很多方法可以做到這一點,但更好的人可以回覆。 – 2009-11-10 22:59:42