C++ 經驗條款

jopen 10年前發布 | 11K 次閱讀 C/C++開發 C/C++

C++經驗談:

一、絕不讓構造函數稱為虛函數:

         從最簡單的思想來看,C++對象模型中是根據虛函數表來管理虛函數的,那么在調用虛函數時,需要找到虛函數表,在對象沒有創建成功時是沒有虛函數表指針的,構造函數就是構造對象的,在對象沒有創建成功之前來尋找虛函數表是不合理的。

         一般情況下,編譯器會為每個類生成一個公有的默認構造函數,但是有兩種特殊情況例外:

         一個類顯示聲明了構造函數,這種情況下編譯器不會生成公有默認構造函數,如果程序需要一個默認構造函數,則需要程序員顯示地提供。

         一個類聲明了一個非Public的構造函數,編譯器不會生成公有的默認構造函數。

         如果類有繼承,那么首先完成基類的構造,再完成繼承類的構造,在析構時,順序相反。

         如果基類有virtual函數,那么在繼承類的構造中還需要有虛函數表的創建。

 

         關于拷貝構造函數的調用:

         當類的一個對象去初始化該類的另一個對象時,拷貝構造函數會被調用。

         如果函數的形參是類的對象,調用函數進行形參和實參的結合時,拷貝構造函數會被調用。

         如果函數的返回值是類對象,函數調用完成返回時,拷貝構造函數會被調用。

 

避免在構造/析構函數中調用虛函數:

         基類的構造函數會在派生類構造函數執行之前被調用,所以當基類構造函數運行時,派生類的數據成員都沒有進行初始化。

         虛函數的調用機制完全由基類控制,所以如果基類沒有完成構造,虛函數的調用機制(既虛函數表)沒有完成初始化,通過虛函數實現的所有期望操作都將失敗。

 

Class對象大小與什么有關系:

         如果一個class中無任何數據成員,那class的大小時1.

         Class中對象的大小僅與對象的數據成員大小有關系,而與對象的函數成員無任何關系。

         Class對象非靜態數據成員占用內存大小會影響對象大小

         Class對象采用的內存對齊策略會影響類對象大小

         Class對象中數據成員不會影響對象大小

         Class中virtual函數會影響類對象大小,因為virtual-talbe的原因虛函數占4字節空間

關于虛繼承影響對象大小:

         由于涉及虛函數表和虛基表,會同時增加一個(剁成繼承下對應多個)vfptr指針指向虛函數表vftable和一個vbptr指針指向虛基表 vbtable,這兩者所占的空間大小為:8(或者8乘以多繼承時父類的個數),記住有各自的虛函數表指針和虛基類指針,都共享虛基類指針即可。

         類對象的大小影響因素不包括靜態數據成員,因為累中的靜態數據成員分布于全局存儲區域,不占用類對象的空間。

 

運算符重載:

         不要重載&&和||運算符,因為重載&&和||,會導致&&和||失去簡短求值功能。

         如果一個重載操作符是類成員,那么只有當和它一起被使用的左操作數是該類對象時,它才會被調用。如果該操作符的左操作數必須是其他類型,那么重載操作符必須是命名空間成員。

 

Public private protected三種繼承方法:

         Public繼承時最常用的繼承機制,public繼承時子類具有最大的權限,公有繼承的特點是基類公有成員和保護成員作為派生類的成員時,他們都保持原有的狀態,而基類的私有成員仍然是私有的。

         Protected是一種比較有特點的繼承機制。保護繼承的特點是基類的所有公有成員和保護成員都成為派生類的保護成員,并且只能被它的派生類成員函數或友元函數訪問,基類的私有成員仍然是私有的。

         Private是一種比較少見的繼承方法,私有繼承的特點是基類的公有成員和保護成員都作為派生類的私有成員,并且不能被這個派生類的子類所訪問。

 

         單繼承在構造時,首先是構造基類,然后是進程自身的構造。如果基類仍然存在上層基類,則首先進行上層基類的構造,然后再構造基類,析構的順序和構造的順序是嚴格按照構造順序的逆序進行的。

 

         不要重新定義繼承而來的非虛函數,以防止產生函數覆蓋現象。

 

         帶默認參數的virtual函數實現時,虛函數采用動態綁定,默認參數采用靜態綁定。在基類虛函數中聲明的默認參數,即使派生類中重新指定了默認參數,在多態調用時,依然采用基類虛函數中的默認參數

 

         不要試圖嘗試重載虛函數。

 

 傳值調用、引用傳值、指針傳值三種方式的區別和聯系:

1、  值傳遞過程中,被調函數的形式參數作為被調函數的局部變量處理,即使堆棧中開辟內存空間以存放由主調函數傳進來的實參值,從而成為實參的一個副本,值傳遞的特點是被調函數對形式參數的任何操作都作為局部變量進行,不會影響主調函數的實參變量的值,如果想通過傳值方式實現兩數據的交換,這種方法不可取。

2、  引用傳遞過程中,被調函數的形式參數雖然也作為局部變量在堆棧中開辟了內存空間,但是這時存放的是由主調函數放進來的實參變量的地址。被調用函數對形參的任何操作都被處理成指針間接尋址,即通過堆棧中存放的地址訪問主調函數中的實參變量。正因為如此,被調函數對形參做任何操作都影響主調函數中的實參變量。

3、  指針傳遞時傳值調用的特例,即傳的值為主調函數變量的地址。被調函數的形式參數同樣在堆棧中為局部變量開辟了內空間,被調函數對局部變量的任何操作都會作用在主調函數變量的地址之上。因此被調函數通過局部形參所做的任何操作都會影響主調函數中的實參變量。

 傳值調用、引用傳值、指針傳值三種方式的區別和聯系:

1、  值傳遞過程中,被調函數的形式參數作為被調函數的局部變量處理,即使堆棧中開辟內存空間以存放由主調函數傳進來的實參值,從而成為實參的一個副本,值傳遞的特點是被調函數對形式參數的任何操作都作為局部變量進行,不會影響主調函數的實參變量的值,如果想通過傳值方式實現兩數據的交換,這種方法不可取。

2、  引用傳遞過程中,被調函數的形式參數雖然也作為局部變量在堆棧中開辟了內存空間,但是這時存放的是由主調函數放進來的實參變量的地址。被調用函數對形參的任何操作都被處理成指針間接尋址,即通過堆棧中存放的地址訪問主調函數中的實參變量。正因為如此,被調函數對形參做任何操作都影響主調函數中的實參變量。

3、  指針傳遞時傳值調用的特例,即傳的值為主調函數變量的地址。被調函數的形式參數同樣在堆棧中為局部變量開辟了內空間,被調函數對局部變量的任何操作都會作用在主調函數變量的地址之上。因此被調函數通過局部形參所做的任何操作都會影響主調函數中的實參變量。

來自:http://blog.csdn.net/yusiguyuan/article/details/41620761

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!