Effective C++改善程序與設計的55個具體做法 學習筆記(三)

目錄

(1)條款08:別讓異常逃離析構函數(這條理解的不好,看官可忽略或者幫我理解理解)

(2)條款09:絕不在構造和析構過程中調用virtual函數

(3)條款10:令operator = 返回一個reference to *this。

(4)條款11:在operator=中處理“自我賦值”

(5)條款12:複製對象時勿忘其每一個成分


人生美好,今日之工乃爲明日之秀,666

接上篇文章https://mp.csdn.net/console/editor/html/106558956

(1)條款08:別讓異常逃離析構函數(這條理解的不好,看官可忽略或者幫我理解理解)

簡單的說就是析構函數出BUG可能會導致程序退出的時候崩潰或者中斷。

舉個例子,你寫了一個程序,每次點擊一個按鈕就會,創建100個座位的屋子,classA申請10個,classB申請10個空間,點擊關閉析構的時候先析構classA,再析構classB,如果classA的析構函數出現異常,就無法進行classB的析構,導致classB析構失敗,程序造成內存泄漏。(等等!我程序異常退出了,內存都釋放了,所以異常退出這個例子並沒有很嚴重,析構一旦失敗程序就會結束,這個可能是平臺等相關的,後續有機會討論)

 

書中給出的辦法,比如我這裏想確保數據庫已經被關閉,那麼就需要再來一個函數close來確保程序關閉數據庫。

(2)條款09:絕不在構造和析構過程中調用virtual函數

在構造和析構函數中不要調用虛函數。

在C++繼承關係中,父類指針實例化子類對象是會先走父類的構造函數的,走父類的構造函數時如果調用虛函數調用的則是父類的虛函數。與我們想要達成的效果(調用子類的重載虛函數)不同。

如下:

父類

class MyClass
{
public:
    MyClass();
    virtual void setData();
    int b;
};

MyClass::MyClass()
{
    setData();
}

void MyClass::setData()
{
    b = 10;
}

子類:

class MySon : public MyClass
{
public:
    MySon();
    virtual void setData() override;
};

MySon::MySon()
{

}

void MySon::setData()
{
    b = 10*10;
}

我們調用:

    MyClass *p_myClass = new MySon;
    printf("%d\n",p_myClass->b);

打印結果爲10。

這裏可以看到,我們在調用過程中調用的是父類的虛函數實現,而不是子類的虛函數實現。

解決方案:就別在析構函數中寫虛函數。或者讓子類也走一遍該函數(不好管理)。可以用一個init函數來讓用戶手動調用想要調用的函數。

(3)條款10:令operator = 返回一個reference to *this。

這個是爲了連續賦值功能。

Widget & operator=(const Widget & rhs)
{
    ...//賦值操作
    return *this;//返回自身
}

(4)條款11:在operator=中處理“自我賦值”

這裏就是用到swap函數來處理。

先說問題,如果自我賦值了,可能會導致“指針指向一個已經被刪除的對象”。

(5)條款12:複製對象時勿忘其每一個成分

這條適用於拷貝構造函數或“=”運算符。在寫這些函數的時候要確保每一個成員變量都被正確拷貝複製。

注意:不要用一個賦值函數來調用另一個賦值函數,應該將重複代碼再起一個函數供這兩個函數調用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章