2014-03-04 101 views
2

我有以下類別:這是隱式地調用一個拷貝構造函數嗎?

class Player 
{ 
public: 
    Inventory& GetInventory() 
    { 
     return inventory; 
    } 
private: 
    Inventory inventory; 
}; 

class Inventory 
{ 
    // Methods removed for brevity 
private: 
    std::vector<std::string> items; 
}; 

我想要做的就是讓代碼的用戶修改的Player::inventory內容,而不能重新分配給不同的對象。簡單的例子:

Player player; 

// OK: I want to able to add items. 
player.GetInventory().AddItem("Item 1"); 

// Not OK: I don't want to be able to assign 
// Player::inventory to a different Inventory. 
Inventory badInventory; 
player.GetInventory() = badInventory; 

我知道我可以通過修改GetInventory()返回Inventory* const做到這一點,但這種情況下是讓我懷疑什麼,我認爲是引用的事實。我相信他們:

  1. 不是對象本身,所以沒有地址。
  2. 無法在其生命週期內重新分配。
  3. 聲明時必須初始化。

對我說badInventory必須以某種方式被隱式複製。所以我定義了一個拷貝構造函數,希望能記錄電話,就像這樣:

Inventory(const Inventory& rhs) 
{ 
    std::cout << "Copy ctor." << std::endl; 
} 

但是,這永遠不會觸發。所以我的問題歸結爲:這一行發生了什麼?

player.GetInventory() = badInventory; 

我在這裏失去了一些東西,但我不知道它是什麼。

回答

6

該行實際上調用了複製賦值操作符,而不是複製構造函數。這是宣佈爲

Inventory& operator=(const Inventory&); 

注意player.GetInventory()已經存在對象的功能,所以它不能調用拷貝構造函數,僅僅是因爲你沒有任何建設。

如果你想禁止被複制庫存,刪除這些功能:

Inventory(const Inventory&) = delete; 
Inventory& operator=(const Inventory&) = delete; 

或者,如果你的編譯器沒有C++ 11的支持,聲明爲private,並沒有提供一個定義。

private: 
    Inventory(const Inventory&); 
    Inventory& operator=(const Inventory&); 
+0

感謝您的回答。只是爲了澄清,當你說:'請注意,player.GetInventory()是一個已經存在的對象,所以它不能調用複製構造函數,它只適用於複製構造函數,而不適用於複製指定構造函數?另外,這是否意味着我在這裏的一般用法是通過使用'Inventory * const GetInventory()'來促進'Player'的封裝,假設我只是想阻止重新分配'Player :: inventory',不妨礙複製庫存本身? –

+0

@John查看'初始化'與'賦值'。 – 2014-03-04 17:26:15

+0

@remyabel我知道他們之間的區別。我只是沒有意識到第二種類型的拷貝構造函數,所以我確信評論中沒有錯誤,只是爲了確保。 –

1

在這種scenarion

player.GetInventory() = badInventory; 

有用於類庫存的拷貝賦值運算符。

您可以將複製/移動賦值運算符定義爲已刪除。例如

class Inventory 
{ 
public: 
    Inventory & operator =(const Inventory &) = delete; 
    Inventory & operator =(Inventory &&) = delete; 
    // Methods removed for brevity 
private: 
    std::vector<std::string> items; 
}; 

或者你可以將它們聲明爲私有成員函數。

雖然在我看來,這將是更好,如果你需要定義所有需要處理矢量作爲成員函數,而不是參考了久違的矢量

+0

感謝您的回答,但我沒有返回對矢量的引用。 'AddItems'以及其他函數被定義爲'Inventory'的成員函數。因此,它們不會將該向量公開爲'Inventory'的公共接口的一部分。 –

相關問題