2016-04-14 70 views
0

我正在看PIMPL成語的一個例子,並且我發現了一行代碼,我真的不明白。由於我剛接觸C++和OOP,我希望有人能夠解釋這個函數的功能。帶結構指針的類初始化列表

有人可以澄清這個功能嗎?

PublicClass::PublicClass(const PublicClass& other) 
    : d_ptr(new CheshireCat(*other.d_ptr)) { // <------- This line 
    // do nothing 
} 

/

這裏是例子。

//header file: 
class PublicClass { 
public: 
    PublicClass();        // Constructor 
    PublicClass(const PublicClass&);   // Copy constructor 
    PublicClass(PublicClass&&);     // Move constructor 
    PublicClass& operator=(const PublicClass&); // Copy assignment operator 
    ~PublicClass();        // Destructor 
    // Other operations... 

private: 
    struct CheshireCat;       // Not defined here 
    unique_ptr<CheshireCat> d_ptr;    // opaque pointer 
}; 

/

//CPP file: 
#include "PublicClass.h" 

struct PublicClass::CheshireCat { 
    int a; 
    int b; 
}; 

PublicClass::PublicClass() 
    : d_ptr(new CheshireCat()) { 
    // do nothing 
} 

PublicClass::PublicClass(const PublicClass& other) 
    : d_ptr(new CheshireCat(*other.d_ptr)) { 
    // do nothing 
} 

PublicClass::PublicClass(PublicClass&& other) 
{ 
    d_ptr = std::move(other.d_ptr); 
} 

PublicClass& PublicClass::operator=(const PublicClass &other) { 
    *d_ptr = *other.d_ptr; 
    return *this; 
} 

PublicClass::~PublicClass() {} 

回答

1

C++缺省提供一種複製構造,當用戶沒有定義之一:http://en.cppreference.com/w/cpp/language/copy_constructor

線:

d_ptr(new CheshireCat(*other.d_ptr)) 

被簡單地取消引用一個指針到現有CheshireCat對象並將其複製到實例化一個新的CheshireCat對象,d_ptr到實例化對象指向。

+0

技術上不正確。 C++不提供*瑣碎的*拷貝構造函數,它提供*默認的*。 – SergeyA

+0

閱讀引用的鏈接下的Trivial Copy構造函數:「類T的複製構造函數是微不足道的,如果滿足以下所有條件: 它不是用戶提供的(即它是隱式定義或默認),並且如果它是默認的,它的簽名與隱含定義相同; T沒有虛擬成員函數; T沒有虛擬基類; 爲T的每個直接基地選擇的複製構造函數是微不足道的; 選擇了複製構造函數對於T的每個非靜態類類型(或類類型數組)都是微不足道的;「 –

+1

你自己的鏈接與你相矛盾。 '爲T的每個非靜態類類型(或類類型數組)的成員選擇的拷貝構造函數是微不足道的'。這裏沒有任何暗示'CheshireCat'構造函數是微不足道的。同樣,正確的定義是「......提供**默認**拷貝構造函數......」。有時候這些默認構造函數是微不足道的,有時它們不是,它與問題無關。 – SergeyA

2

的結構不 「取值」。 功能取值。構造函數是函數。在new CheshireCat(*other.d_ptr)中,您調用編譯器生成的拷貝構造函數CheshireCat

您也不必不傳遞一個指針而是一個參考,因爲取消引用other.d_ptr通過的std::unique_ptr重載operator*。事實上,如果你寫new CheshireCat(other.d_ptr)new CheshireCat(other.d_ptr.get()),那麼你會得到一個編譯錯誤。

1

表達式*other.d_ptr被解析爲等同於*(other.d_ptr)。讓我們以語法d_ptr(new CheshireCat(*other.d_ptr))和工作由內而外,以確定它在做什麼:

  • other - 一個PublicClass const &的聲明。
  • other.d_ptr - a unique_ptr<CheshireCat> const &,對otherd_ptr實例成員的引用。
  • *other.d_ptr - 的operator*unique_ptr對象上的調用,這將產生CheshireCat const &類型(於所述unique_ptr對象擁有的對象的引用)的結果。
  • new CheshireCat(*other.d_ptr) - 以此CheshireCat const &和堆 - 通過調用CheshireCat類型的複製構造函數來分配新的CheshireCat對象。該表達式的類型爲CheshireCat *
  • d_ptr(new CheshireCat(*other.d_ptr)) - 使用CheshireCat *值構造正在構造的PublicClass對象的d_ptr成員。 (這是這個特殊的PublicClass構造的initializer list。)

換句話說,所有的這行做的是複製由other實例擁有的CheshireCat對象,並給予該副本的所有權轉讓給PublicClass對象,正在構建。