對於拷貝建構函式以及賦值建構函式的定義,我就不再囉嗦了,還是給出一個簡單的例子,更直觀些吧。 class CStr { public: CStr(); //預設建構函式 CStr(const char* psz); //一種廣義拷貝建構函式,不過也有人不認同我的看法 CStr(const CStr& str); //拷貝建構函式 const CStr& operator=(const CStr& str); //賦值建構函式 size_t GetSize() const; //這裡的const是什麼意思?它必須嗎? operator const char*() const { return m_pdata; } protected: const CStr* _Copy(const CStr& str); private: char* m_pdata; size_t m_size; }; CStr::CStr() { m_pdata = NULL; m_size = 0; } size_t CStr::GetSize() const { return m_size; } const CStr* CStr::_Copy(const CStr& str) { if(this != &str) { if(m_pdata){ delete[] m_pdata; } m_size = str.GetSize(); m_pdata = new char[m_size + 1]; assert(m_pdata); strcpy(m_pdata, str); } return this; } CStr::CStr(const char* psz) : m_pdata(NULL), m_size(0) { assert(psz); if(m_pdata != psz) { if(m_pdata){ delete[] m_pdata; } m_size = strlen(psz); m_pdata = new char[m_size + 1]; assert(m_pdata); strcpy(m_pdata, psz); } } CStr::CStr(const CStr& str): m_pdata(NULL), m_size(0) { _Copy(str); } const CStr& CStr::operator=(const CStr& str) { return *(_Copy(str)); } int main() { const char* psz = "test"; const char* psz1 = "me"; CStr str(psz); //拷貝建構函式,此處調用的是CStr(const char* psz)。 #1 CStr str2(str); // 拷貝建構函式,此處調用的是 CStr(const CStr& str) #2 CStr str1 = psz1; // 拷貝構造,str1此前並不存在,現在要先構造它。 #3 str = str1; // 真正的賦值建構函式 #4 return 0; } 上面這個小型的例子,是我剛剛為大家編寫的,這個例子主要就是為了闡述賦值建構函式與拷貝建構函式之間的區別,其實,我的看法是,賦值建構函式不應該被稱為一個建構函式,充其量只能算得上一個重載的操作符函數。 在C語言中,我們知道"=="是判等操作符,而"="卻是一個賦值操作符,所以只要沒有出現"="操作符,也就不會有賦值操作可言。 我之所以認為賦值建構函式不應該被稱為一個建構函式,是因為在調用賦值建構函式的時候,類對象已經存在,自然談不上構造類對象,它只是對該已經存在的類對象的成員變數進行修改(所謂的賦值)操作。而拷貝建構函式是利用一個已經存在的類物件建構出一個新的類對象。 回到上面的例子,相信大多數人都應該能分清#1、#2、#4所調用的函數,而對於#3,我想著重說明的是:賦值構造的實際用意是修改一個已有的對象,而現在str1還沒有被定義,所以此處還是必須要調用拷貝建構函式先產生一個CStr對象。 最後,請大家記住:定義與賦值同時進行的話,必須要先定義,所以必須得先調用拷貝建構函式,而對於符合單純的賦值操作文法的語句(也就是只有兩個運算元的運算式)來說,才是真正的調用賦值建構函式。如果大家有什麼問題,可以問我,我會儘力為大家講解。 |