class CMessage { private: char * m_pMessage; public: void showIt()const { cout << m_pMessage << endl; } //構造函數 CMessage(const char* text="Default message") { cout << "Constructor difinition" << endl; size_t length{strlen(text)+1}; m_pMessage = new char[length+1]; strcpy_s(m_pMessage,length+1,text); } //復制構造函數 CMessage(const CMessage & aMess) { size_t len{strlen(aMess.m_pMessage)+1}; this->m_pMessage = new char[len]; strcpy_s(m_pMessage,len,aMess.m_pMessage); } //重載賦值運算符 CMessage & operator=(const CMessage & aMess) { if (this!= &aMess) { delete[]m_pMessage; size_t length{strlen(aMess.m_pMessage)+1}; m_pMessage = new char[length]; strcpy_s(this->m_pMessage,length,aMess.m_pMessage); } return *this; } //析構函數 ~CMessage() { cout << "Destructor called" << endl; delete[]m_pMessage; } }; int main() { CMessage motto1{"Amiss is as good as a mile"}; CMessage motto2; motto2 = motto1; motto2.showIt(); motto1.showIt(); return 0; }
復制構造函數:
當某個類動態的為數據成員分配空間,又利用按值傳遞給函數傳遞該類的對象,那麼必須要實現復制構造函數
如:
motto2 {motto1};
或
CMessage & displayMessage(CMessage localMsg)
{
cout <<"the message is:----------------" << endl;
localMsg.showIt();
return *this;
}
都會出現異常,如果沒有實現復制構造函數,即兩個對象的指針指向了同一塊地址區域。
重載賦值運算符:
以現有的同類對象進行初始化類的對象,或者通過按值傳遞方式給函數傳遞對象,調用默認復制構造函數。
當賦值語句的左邊和右邊是同類類型的對象時,調用默認賦值運算符。
如:
motto2 = motto1;
如果我們沒有實現賦值運算符函數,編譯器就會使用默認的賦值運算符函數,當為數據成員動態的分配內存,進行對象賦值,就會程序異常。
因為兩個對象都有一個指向相同內存地址的指針。
分析賦值運算符函數:
CMessage & operator=(const CMessage & aMess)
{ if (this!= &aMess)
{
delete[]m_pMessage;
size_t length{strlen(aMess.m_pMessage)+1};
m_pMessage = new char[length];
strcpy_s(this->m_pMessage,length,aMess.m_pMessage);
}
return *this;
}
delete[]m_pMessage; 刪除分配給第一個對象的內存,重新分配足夠的內存,以容納第二個對象的字符串。
1、當 motto1 = motto1;會發生什麼呢?
賦值運算符函數會釋放 motto1 對象成員指向的內存
所以,if (this!= &aMess) 這條語句,是有必要的。
2、那麼返回對象為什麼?
motto1 = motto2=motto3;
這條語句的原型是:
motto1.operator=(motto2.operator=(motto3));
可知 motto2.operator=(motto3) 的結果必須是對象才能作為 motto1.operator=()的參數。
3、那麼返回引用為什麼?
(motto1 = motto2)=motto3;
這條語句的原型是:
(motto1.operator=(motto2)).operator=(motto3);
可知(motto1.operator=(motto2))的結果是個是個返回的臨時對象,它是 rvalue ,編譯器不允許使用 rvalue 調用函數成員。
而返回引用它是 lvalue。