精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

精品文章 論C++構(gòu)造函數(shù)中的不合理設(shè)計(jì)

開發(fā) 后端
本文詳述C++構(gòu)造函數(shù)中的不合理設(shè)計(jì)。在C++中,構(gòu)造函數(shù)是一個(gè)在構(gòu)件對(duì)象的時(shí)候調(diào)用的特殊的函數(shù),其目的是對(duì)對(duì)象進(jìn)行初始化的工作,從而使對(duì)象被使用之前可以處于一種合理的狀態(tài)。但是,構(gòu)造函數(shù)的設(shè)計(jì)并不完美,甚至有些不合理的特性。

  在C++中,構(gòu)造函數(shù)是一個(gè)在構(gòu)件對(duì)象的時(shí)候調(diào)用的特殊的函數(shù),其目的是對(duì)對(duì)象進(jìn)行初始化的工作,從而使對(duì)象被使用之前可以處于一種合理的狀態(tài)。但是,構(gòu)造函數(shù)的設(shè)計(jì)并不完美,甚至有些不合理的特性。比如說,限定構(gòu)造函數(shù)名稱與類的名稱相同的條件。這些特性在構(gòu)造C++編譯器的時(shí)候是值得引起注意的。還有,在今后C++的標(biāo)準(zhǔn)修訂或者制定其他面向?qū)ο蟮脑O(shè)計(jì)語言時(shí)候應(yīng)當(dāng)避免這些特性。這里也提出了一些解決的方案。

[[21117]] 

  C++中,任何類都有一個(gè)(至少有一個(gè))構(gòu)造函數(shù),甚至在沒有構(gòu)造函數(shù)被聲明的時(shí)候亦是如此。在對(duì)象被聲明的時(shí)候,或者被動(dòng)態(tài)生成的時(shí)候,這些構(gòu)造函數(shù)就會(huì)被調(diào)用。構(gòu)造函數(shù)做了許多不可見的工作,即使構(gòu)造函數(shù)中沒有任何代碼,這些工作包括對(duì)對(duì)象的內(nèi)存分配和通過賦值的方式對(duì)成員進(jìn)行初始化。構(gòu)造函數(shù)的名稱必須與類的名稱相同,但是可以有許多不同的重載版本來提供,通過參數(shù)類型來區(qū)分構(gòu)造函數(shù)的版本。構(gòu)造函數(shù)可以顯式的通過用戶代碼來調(diào)用,或者當(dāng)代碼不存在是通過編譯程序來隱式插入。當(dāng)然,顯式地通過代碼調(diào)用是推薦的方法,因?yàn)殡[式調(diào)用的效果可能不是我們所預(yù)料的,特別是在處理動(dòng)態(tài)內(nèi)存分配方面。代碼通過參數(shù)來調(diào)用唯一的構(gòu)造函數(shù)。構(gòu)造函數(shù)沒有返回值,盡管在函數(shù)體中可以又返回語句。每個(gè)構(gòu)造函數(shù)可以以不同的方式來實(shí)例化一個(gè)對(duì)象,因?yàn)槊總€(gè)類都有構(gòu)造函數(shù),至少也是缺省構(gòu)造函數(shù),所以每個(gè)對(duì)象在使用之前都相應(yīng)的使用構(gòu)造函數(shù)。

  因?yàn)闃?gòu)造函數(shù)是一種函數(shù),所以他的可見性無非是三種public、private、protected。通常,構(gòu)造函數(shù)都被聲明為public型。如果構(gòu)造函數(shù)被聲明為private或protected,就限制了對(duì)象的實(shí)例化。這在阻止類被其他人實(shí)例化的方面很有效。構(gòu)造函數(shù)中可以有任何C++的語句,比如,一條打印語句,可以被加入到構(gòu)造函數(shù)中來表明調(diào)用的位置。

#p#

  構(gòu)造函數(shù)的類型

  C++中構(gòu)造函數(shù)有許多種類型,最常用的式缺省構(gòu)造函數(shù)和拷貝構(gòu)造函數(shù),也存在一些不常用的構(gòu)造函數(shù)。下面介紹了四種不同的構(gòu)造函數(shù)。

  1、缺省構(gòu)造函數(shù)

  缺省構(gòu)造函數(shù)是沒有參數(shù)的函數(shù)。另外,缺省構(gòu)造函數(shù)也可以在參數(shù)列表中以參數(shù)缺省值的方式聲明。缺省構(gòu)造函數(shù)的作用是把對(duì)象初始化為缺省的狀態(tài)。如果在類中沒有顯式定義構(gòu)造函數(shù),那么編譯器會(huì)自動(dòng)的隱式創(chuàng)建一個(gè),這個(gè)隱式創(chuàng)建的構(gòu)造函數(shù)和一個(gè)空的構(gòu)造函數(shù)很相像。他除了產(chǎn)生對(duì)象的實(shí)例以外什么工作都不做。在許多情況下,缺省構(gòu)造函數(shù)都會(huì)被自動(dòng)的調(diào)用,例如在一個(gè)對(duì)象被聲明的時(shí)候,就會(huì)引起缺省構(gòu)造函數(shù)的調(diào)用。

  2、拷貝構(gòu)造函數(shù)

  拷貝構(gòu)造函數(shù),經(jīng)常被稱作X(X&),是一種特殊的構(gòu)造函數(shù),他由編譯器調(diào)用來完成一些基于同一類的其他對(duì)象的構(gòu)件及初始化。它的唯一的一個(gè)參數(shù)(對(duì)象的引用)是不可變的(因?yàn)槭莄onst型的)。這個(gè)函數(shù)經(jīng)常用在函數(shù)調(diào)用期間于用戶定義類型的值傳遞及返回??截悩?gòu)造函數(shù)要調(diào)用基類的拷貝構(gòu)造函數(shù)和成員函數(shù)。如果可以的話,它將用常量方式調(diào)用,另外,也可以用非常量方式調(diào)用。

  在C++中,下面三種對(duì)象需要拷貝的情況。因此,拷貝構(gòu)造函數(shù)將會(huì)被調(diào)用。

  1). 一個(gè)對(duì)象以值傳遞的方式傳入函數(shù)體

  2). 一個(gè)對(duì)象以值傳遞的方式從函數(shù)返回

  3). 一個(gè)對(duì)象需要通過另外一個(gè)對(duì)象進(jìn)行初始化

  以上的情況需要拷貝構(gòu)造函數(shù)的調(diào)用。如果在前兩種情況不使用拷貝構(gòu)造函數(shù)的時(shí)候,就會(huì)導(dǎo)致一個(gè)指針指向已經(jīng)被刪除的內(nèi)存空間。對(duì)于第三種情況來說,初始化和賦值的不同含義是構(gòu)造函數(shù)調(diào)用的原因。事實(shí)上,拷貝構(gòu)造函數(shù)是由普通構(gòu)造函數(shù)和賦值操作賦共同實(shí)現(xiàn)的。描述拷貝構(gòu)造函數(shù)和賦值運(yùn)算符的異同的參考資料有很多。

  拷貝構(gòu)造函數(shù)不可以改變它所引用的對(duì)象,其原因如下:當(dāng)一個(gè)對(duì)象以傳遞值的方式傳一個(gè)函數(shù)的時(shí)候,拷貝構(gòu)造函數(shù)自動(dòng)的被調(diào)用來生成函數(shù)中的對(duì)象。如果一個(gè)對(duì)象是被傳入自己的拷貝構(gòu)造函數(shù),它的拷貝構(gòu)造函數(shù)將會(huì)被調(diào)用來拷貝這個(gè)對(duì)象這樣復(fù)制才可以傳入它自己的拷貝構(gòu)造函數(shù),這會(huì)導(dǎo)致無限循環(huán)。

  除了當(dāng)對(duì)象傳入函數(shù)的時(shí)候被隱式調(diào)用以外,拷貝構(gòu)造函數(shù)在對(duì)象被函數(shù)返回的時(shí)候也同樣的被調(diào)用。換句話說,你從函數(shù)返回得到的只是對(duì)象的一份拷貝。但是同樣的,拷貝構(gòu)造函數(shù)被正確的調(diào)用了,你不必?fù)?dān)心。

  如果在類中沒有顯式的聲明一個(gè)拷貝構(gòu)造函數(shù),那么,編譯器會(huì)私下里為你制定一個(gè)函數(shù)來進(jìn)行對(duì)象之間的位拷貝(bitwise copy)。這個(gè)隱含的拷貝構(gòu)造函數(shù)簡單的關(guān)聯(lián)了所有的類成員。許多作者都會(huì)提及這個(gè)默認(rèn)的拷貝構(gòu)造函數(shù)。注意到這個(gè)隱式的拷貝構(gòu)造函數(shù)和顯式聲明的拷貝構(gòu)造函數(shù)的不同在于對(duì)于成員的關(guān)聯(lián)方式。顯式聲明的拷貝構(gòu)造函數(shù)關(guān)聯(lián)的只是被實(shí)例化的類成員的缺省構(gòu)造函數(shù)除非另外一個(gè)構(gòu)造函數(shù)在類初始化或者在構(gòu)造列表的時(shí)候被調(diào)用。

  拷貝構(gòu)造函數(shù)是程序更加有效率,因?yàn)樗挥迷贅?gòu)造一個(gè)對(duì)象的時(shí)候改變構(gòu)造函數(shù)的參數(shù)列表。設(shè)計(jì)拷貝構(gòu)造函數(shù)是一個(gè)良好的風(fēng)格,即使是編譯系統(tǒng)提供的幫助你申請(qǐng)內(nèi)存默認(rèn)拷貝構(gòu)造函數(shù)。事實(shí)上,默認(rèn)拷貝構(gòu)造函數(shù)可以應(yīng)付許多情況。

  3、用戶定義的構(gòu)造函數(shù)

  用戶定義的構(gòu)造函數(shù)允許對(duì)象在被定義的時(shí)候同時(shí)被初始化。這種構(gòu)造函數(shù)可以有任何類型的參數(shù)。一個(gè)用戶定義的和其它類型的構(gòu)造函數(shù)在類 mystring 中得以體現(xiàn):

  1. class mystring   
  2. {......  
  3. public: mystring(); // Default constructor  
  4. mystring (mystring &src)  
  5. // Copy constructor  
  6. mystring (char * scr);  
  7. // Coercion constructor  
  8. mystring ( char scr[ ], size_t len);  
  9. // User-Defined constructor  
  10. }; 

  4、強(qiáng)制構(gòu)造函數(shù)

  C++中,可以聲明一個(gè)只有一個(gè)參數(shù)的構(gòu)造函數(shù)來進(jìn)行類型轉(zhuǎn)換。強(qiáng)制構(gòu)造函數(shù)定一個(gè)從參數(shù)類型進(jìn)行的一個(gè)類型轉(zhuǎn)換(隱式的或顯式的)。換句話說,編譯器可以用任何參數(shù)的實(shí)例來調(diào)用構(gòu)造函數(shù)。這樣做的目的是建立一個(gè)臨時(shí)實(shí)例來替換一個(gè)參數(shù)類型的實(shí)例。注意標(biāo)準(zhǔn)新近加入C++的關(guān)鍵字explicit 是用來禁止隱式的類型轉(zhuǎn)換。然而,這一特性還沒能被所有的編譯器支持。下面是一個(gè)強(qiáng)制構(gòu)造函數(shù)的例子:

  1. class A   
  2. {  
  3. public :  
  4. A(int ){ }  
  5. };  
  6. void f(A) { }   
  7. void g()  
  8. {  
  9. A My_Object= 17;  
  10. A a2 = A(57);  
  11. A a3(64);  
  12. My_Object = 67;  
  13. f(77);  
  14. };  

  像A My_Object= 17;這種聲明意味著A(int)構(gòu)造函數(shù)被調(diào)用來從整型變量生成一個(gè)對(duì)象。這樣的構(gòu)造函數(shù)就是強(qiáng)制構(gòu)造函數(shù)。

#p#

  不合理普遍特性

  下面是一些C++構(gòu)造函數(shù)的不合理設(shè)計(jì),當(dāng)然,可能還有其他一些不合理之處。但是,大多數(shù)情況下,我們還是要和這些特性打交道,我們要逐一說明。

  1、構(gòu)造函數(shù)可以為內(nèi)聯(lián),但不要這樣做

  一般來講,大多數(shù)成員函數(shù)都可以在前面加入"inline"關(guān)鍵字而成為內(nèi)聯(lián)函數(shù),構(gòu)造函數(shù)也不例外,但是別這么做!一個(gè)被定義為內(nèi)聯(lián)的構(gòu)造函數(shù)如下:

  1. class x   
  2. {..........  
  3. public : x (int );  
  4. :  
  5. :  
  6. };  
  7. inline x::x(int )  
  8. {...}  

  在上面的代碼中,函數(shù)并不是作為一個(gè)單獨(dú)的實(shí)體而是被插入到程序代碼中。這對(duì)于只有一兩條語句的函數(shù)來說會(huì)提到效率,因?yàn)檫@里沒有調(diào)用函數(shù)的開銷。

  用內(nèi)聯(lián)的構(gòu)造函數(shù)的危險(xiǎn)性可以在定義一個(gè)靜態(tài)內(nèi)聯(lián)構(gòu)造函數(shù)中體現(xiàn)。在這種情況下,靜態(tài)的構(gòu)造函數(shù)應(yīng)當(dāng)是只被調(diào)用一次。然而,如果頭文件中含有靜態(tài)內(nèi)聯(lián)構(gòu)造函數(shù),并被其他單元包括的話,函數(shù)就會(huì)產(chǎn)生多次拷貝。這樣,在程序啟動(dòng)時(shí)就會(huì)調(diào)用所有的函數(shù)拷貝,而不是程序應(yīng)當(dāng)調(diào)用的一份拷貝。這其中的根本原因是靜態(tài)函數(shù)是在以函數(shù)偽裝下的真實(shí)對(duì)象。

  應(yīng)該牢記的一件事是內(nèi)聯(lián)是建議而不是強(qiáng)制,編譯器產(chǎn)生內(nèi)聯(lián)代碼。這意味著內(nèi)聯(lián)是與實(shí)現(xiàn)有關(guān)的編譯器的不同可能帶來很多差異。另一方面,內(nèi)聯(lián)函數(shù)中可能包括比代碼更多的東西。構(gòu)造函數(shù)被聲明為內(nèi)聯(lián),所有包含對(duì)象的構(gòu)造函數(shù)和基類的構(gòu)造函數(shù)都需要被調(diào)用。這些調(diào)用是隱含在構(gòu)造函數(shù)中的。這可能會(huì)創(chuàng)建很大的內(nèi)聯(lián)函數(shù)段,所以,不推薦使用內(nèi)聯(lián)的構(gòu)造函數(shù)。

  2、構(gòu)造函數(shù)沒有任何返回類型

  對(duì)一個(gè)構(gòu)造函數(shù)指定一個(gè)返回類型是一個(gè)錯(cuò)誤,因?yàn)檫@樣會(huì)引入構(gòu)造函數(shù)的地址。這意味著將無法處理出錯(cuò)。這樣,一個(gè)構(gòu)造函數(shù)是否成功的創(chuàng)建一個(gè)對(duì)象將不可以通過返回之來確定。事實(shí)上,盡管C++的構(gòu)造函數(shù)不可以返回,也有一個(gè)方法來確定是否內(nèi)存分配成功地進(jìn)行。這種方法是內(nèi)建在語言內(nèi)部來處理緊急情況的機(jī)制。一個(gè)預(yù)定好的函數(shù)指針 new-handler,它可以被設(shè)置為用戶定制的對(duì)付new操作符失敗的函數(shù),這個(gè)函數(shù)可以進(jìn)行任何的動(dòng)作,包括設(shè)置錯(cuò)誤標(biāo)志、重新申請(qǐng)內(nèi)存、退出程序或者拋出異常。你可以安心的使用系統(tǒng)內(nèi)建的new-handler。最好的使構(gòu)造函數(shù)發(fā)出出錯(cuò)信號(hào)的方法,就是拋出異常。在構(gòu)造函數(shù)中拋出異常將清除錯(cuò)誤之前創(chuàng)建的任何對(duì)象及分配的內(nèi)存。

  如果構(gòu)造函數(shù)失敗而使用異常處理的話,那么,在另一個(gè)函數(shù)中進(jìn)行初始化可能是一個(gè)更好的主意。這樣,程序員就可以安全的構(gòu)件對(duì)象并得到一個(gè)合理的指針。然后,初始化函數(shù)被調(diào)用。如果初始化失敗的話,對(duì)象直接被清除。

  3、構(gòu)造函數(shù)不可以被聲明為static

  C++中,每一個(gè)類的對(duì)象都擁有類數(shù)據(jù)成員的一份拷貝。但是,靜態(tài)成員則沒有這樣而是所有的對(duì)象共享一個(gè)靜態(tài)成員。靜態(tài)函數(shù)是作用于類的操作,而不是作用在對(duì)象上??梢杂妙惷妥饔每刂撇僮鞣麃碚{(diào)用一個(gè)靜態(tài)函數(shù)。這其中的一個(gè)例外就是構(gòu)造函數(shù),因?yàn)樗`反了面向?qū)ο蟮母拍睢?/p>

  關(guān)于這些的一個(gè)相似的現(xiàn)象是靜態(tài)對(duì)象,靜態(tài)對(duì)象的初始化是在程序的一開始階段就進(jìn)行的(在main()函數(shù)之前)。下面的代碼解釋了這種情況。

  1. MyClass static_object(88, 91);  
  2.  
  3. void bar()  
  4. {  
  5. if (static_object.count( ) > 14) {  
  6. ...  
  7. }  
  8. } 

  在這個(gè)例子中,靜態(tài)變量在一開始的時(shí)候就被初始化。通常這些對(duì)象由兩部分構(gòu)成。第一部分是數(shù)據(jù)段,靜態(tài)變量被讀取到全局的數(shù)據(jù)段中。第二部分是靜態(tài)的初始化函數(shù),在main()函數(shù)之前被調(diào)用。我們發(fā)現(xiàn),一些編譯器沒有對(duì)初始化的可靠性進(jìn)行檢查。所以你得到的是未經(jīng)初始化的對(duì)象。解決的方案是,寫一個(gè)封裝函數(shù),將所有的靜態(tài)對(duì)象的引用都置于這個(gè)函數(shù)的調(diào)用中,上面的例子應(yīng)當(dāng)這樣改寫。

  1. static MyClass* static_object = 0;  
  2.  
  3. MyClass*  
  4. getStaticObject()  
  5. {  
  6. if (!static_object)  
  7. static_object =   
  8. new MyClass(87, 92);  
  9. return static_object;  
  10. }  
  11.  
  12. void bar()  
  13. {  
  14. if (getStaticObject()->count( ) > 15)  
  15. {  
  16. ...  
  17. }  
  18. } 

  4、構(gòu)造函數(shù)不能成為虛函數(shù)

  虛構(gòu)造函數(shù)意味著程序員在運(yùn)行之前可以在不知道對(duì)象的準(zhǔn)確類型的情況下創(chuàng)建對(duì)象。虛構(gòu)造函數(shù)在C++中是不可能實(shí)現(xiàn)的。最通常遇到這種情況的地方是在對(duì)象上實(shí)現(xiàn)I/O的時(shí)候。即使足夠的類的內(nèi)部信息在文件中給出,也必須找到一種方法實(shí)例化相應(yīng)的類。然而,有經(jīng)驗(yàn)的C++程序員會(huì)有其他的辦法來模擬虛構(gòu)造函數(shù)。

  模擬虛函數(shù)需要在創(chuàng)建對(duì)象的時(shí)候指定調(diào)用的構(gòu)造函數(shù),標(biāo)準(zhǔn)的方法是調(diào)用虛的成員函數(shù)。很不幸,C++在語法上不支持虛構(gòu)造函數(shù)。為了繞過這個(gè)限制,一些現(xiàn)成的方法可以在運(yùn)行時(shí)刻確定構(gòu)件的對(duì)象。這些等同于虛構(gòu)造函數(shù),但是這是C++中根本不存在的東西。

  第一個(gè)方法是用switch或者if-else選擇語句來手動(dòng)實(shí)現(xiàn)選擇。在下面的例子中,選擇是基于標(biāo)準(zhǔn)庫的type_info構(gòu)造,通過打開運(yùn)行時(shí)刻類型信息支持。但是你也可以通過虛函數(shù)來實(shí)現(xiàn)RTTI

  1. class Base  
  2. {  
  3. public:  
  4. virtual const char* get_type_id() const;  
  5. staticBase* make_object  
  6. (const char* type_name);  
  7. };  
  8.  
  9. const char* Base::get_type_id() const 
  10. {  
  11. return typeid(*this).raw_name();  
  12. }  
  13.  
  14. class Child1: public Base  
  15. {  
  16. };  
  17.  
  18. class Child2: public Base  
  19. {  
  20. };  
  21.  
  22. Base* Base::make_object(const char* type_name)  
  23. {  
  24. if (strcmp(type_name,  
  25. typeid(Child1).raw_name()) == 0)  
  26.   return new Child1;  
  27. else if (strcmp(type_name,typeid 
  28.   (Child2).raw_name()) == 0)  
  29. return new Child2;  
  30. else 
  31. {  
  32.  throw exception  
  33. ("unrecognized type name passed");  
  34. return 0X00; // represent NULL  
  35.   }  
  36. } 

  這一實(shí)現(xiàn)是非常直接的,它需要程序員在main_object中保存一個(gè)所有類的表。這就破壞了基類的封裝性,因?yàn)榛惐仨氈雷约旱淖宇悺?/p>

  一個(gè)更面向?qū)ο蟮姆椒惤鉀Q虛構(gòu)造函數(shù)叫做標(biāo)本實(shí)例。它的基本思想是程序中生成一些全局的實(shí)例。這些實(shí)例只再虛構(gòu)造函數(shù)的機(jī)制中存在:

  1. class Base  
  2. {  
  3. public:  
  4.   staticBase* make_object(const chartypename)  
  5. {  
  6.  if (!exemplars.empty())  
  7.  {  
  8.   Base* end = *(exemplars.end());  
  9.   list<Base*>::iterator iter =  
  10.   exemplars.begin();  
  11.   while (*iter != end)  
  12.    {  
  13.     Base* e = *iter++;  
  14.     if (strcmp(typename,  
  15.       e->get_typename()) == 0)  
  16.       return e->clone();  
  17.    }  
  18.  }  
  19.   return 0X00 // Represent NULL;  
  20. }  
  21. virtual ~Base() { };  
  22. virtual const char* get_typename() const 
  23. {  
  24.  return typeid(*this).raw_name();  
  25. }  
  26. virtual Base* clone() const = 0;  
  27. protected:  
  28. static list<Base*> exemplars;  
  29. };  
  30. list<Base*> Base::exemplars;  
  31. // T must be a concrete class  
  32. // derived from Base, above  
  33. template<class T>  
  34. class exemplar: public T  
  35. {  
  36.  public:  
  37.  exemplar()  
  38.  {  
  39.   exemplars.push_back(this);  
  40.  }  
  41. ~exemplar()  
  42.  {  
  43.  exemplars.remove(this);  
  44.  }  
  45. };  
  46. class Child: public Base  
  47. {  
  48.  public:  
  49.  ~Child()  
  50.   {  
  51.   }  
  52.  Base* clone() const 
  53.  {  
  54.   return new Child;  
  55.  }  
  56. };  
  57. exemplar<Child> Child_exemplar;  

  在這種設(shè)計(jì)中,程序員要?jiǎng)?chuàng)建一個(gè)類的時(shí)候要做的是創(chuàng)建一個(gè)相應(yīng)的exampler類。注意到在這個(gè)例子中,標(biāo)本是自己的標(biāo)本類的實(shí)例。這提供了一種高校得實(shí)例化方法。

#p#

  5、創(chuàng)建一個(gè)缺省構(gòu)造函數(shù)

  當(dāng)繼承被使用的時(shí)候,卻省構(gòu)造函數(shù)就會(huì)被調(diào)用。更明確地說,當(dāng)繼承層次的最晚層的類被構(gòu)造的時(shí)候,所有基類的構(gòu)造函數(shù)都在派生基類之前被調(diào)用,舉個(gè)例子來說,看下面的代碼:

  1. #include<iostream.h>  
  2. class Base  
  3. {  
  4.  int x;  
  5.  public :  
  6.     Base() : x(0) { } // The NULL constructor  
  7.     Base(int a) : x(a) { }  
  8. };  
  9. class alpha : virtual public Base  
  10.  {  
  11.  int y;  
  12.  public :  
  13.  alpha(int a) : Base(a), y(2) { }  
  14.  };  
  15. class beta : virtual public Base  
  16.  {  
  17.  int z;  
  18.  public :  
  19.  beta(int a) : Base(a), z(3) { }  
  20.  };  
  21. class gamma : public alpha, public beta  
  22.  {  
  23.   int w;  
  24.   public :  
  25.      gamma ( int a, int b) : alpha(a), beta(b), w(4) { }  
  26.  };  
  27. main()  
  28. {.....  
  29. }  

  在這個(gè)例子中,我們沒有在gamma的頭文件中提供任何的初始化函數(shù)。編譯器會(huì)為基類使用缺省的構(gòu)造函數(shù)。但是因?yàn)槟闾峁┝艘粋€(gè)構(gòu)造函數(shù),編譯器就不會(huì)提供任何缺省構(gòu)造函數(shù)。正如你看到的這段包含缺省構(gòu)造函數(shù)的代碼一樣,如果刪除其中的缺省構(gòu)造函數(shù),編譯就無法通過。

  如果基類的構(gòu)造函數(shù)中引入一些副效應(yīng)的話,比如說打開文件或者申請(qǐng)內(nèi)存,這樣程序員就得確保中間基類沒有初始化虛基類。也就是,只有虛基類的構(gòu)造函數(shù)可以被調(diào)用。

  虛基類的卻省構(gòu)造函數(shù)完成一些不需要任何依賴于派生類的參數(shù)的初始化。你加入一個(gè)init()函數(shù),然后再從虛基類的其他函數(shù)中調(diào)用它,或在其他類中的構(gòu)造函數(shù)里調(diào)用(你的確保它只調(diào)用了一次)。

  6、不能取得構(gòu)造函數(shù)的地址

  C++中,不能把構(gòu)造函數(shù)當(dāng)作函數(shù)指針來進(jìn)行傳遞,指向構(gòu)造函數(shù)的的指針也不可以直接傳遞。允許這些就可以通過調(diào)用指針來創(chuàng)建對(duì)象。一種達(dá)到這種目的的方法是借助于一個(gè)創(chuàng)建并返回新對(duì)象的靜態(tài)函數(shù)。指向這樣的函數(shù)的指針用于新對(duì)象需要的地方。下面是一個(gè)例子:

  1. class A  
  2. {  
  3.  public:  
  4.   A( ); // cannot take the address of this  
  5.      // constructor directly  
  6.  static A* createA();  
  7.    // This function creates a new A object  
  8.    // on the heap and returns a pointer to it.  
  9.    // A pointer to this function can be passed  
  10.    // in lieu of a pointer to the constructor.  
  11. };  

  這一方法設(shè)計(jì)簡單,只需要將抽象類置入頭文件即可。這給new留下了一個(gè)問題,因?yàn)闇?zhǔn)確的類型必須是可見的。上面的靜態(tài)函數(shù)可以用來包裝隱藏子類。

  7、位拷貝在動(dòng)態(tài)申請(qǐng)內(nèi)存的類中不可行

  C++中,如果沒有提供一個(gè)拷貝構(gòu)造函數(shù),編譯器會(huì)自動(dòng)生成一個(gè)。生成的這個(gè)拷貝構(gòu)造函數(shù)對(duì)對(duì)象的實(shí)例進(jìn)行位拷貝。這對(duì)沒有指針成員的類來說沒什么,但是,對(duì)用了動(dòng)態(tài)申請(qǐng)的類就不是這樣的了。為了澄清這一點(diǎn),設(shè)想一個(gè)對(duì)象以值傳遞的方式傳入一個(gè)函數(shù),或者從函數(shù)中返回,對(duì)象是以為拷貝的方式復(fù)制。這種位拷貝對(duì)含有指向其他對(duì)象指針的類是沒有作用的。當(dāng)一個(gè)含有指針的類以值傳遞的方式傳入函數(shù)的時(shí)候,對(duì)象被復(fù)制,包括指針的地址,還有,新的對(duì)象的作用域是這個(gè)函數(shù)。在函數(shù)結(jié)束的時(shí)候,很不幸,析構(gòu)函數(shù)要破壞這個(gè)對(duì)象。因此,對(duì)象的指針被刪除了。這導(dǎo)致原來的對(duì)象的指針指向一塊空的內(nèi)存區(qū)域-一個(gè)錯(cuò)誤。在函數(shù)返回的時(shí)候,也有類似的情況發(fā)生。

  這個(gè)問題可以簡單的通過在類中定義一個(gè)含有內(nèi)存申請(qǐng)的拷貝構(gòu)造函數(shù)來解決,這種靠叫做深拷貝,是在堆中分配內(nèi)存給各個(gè)對(duì)象的。

  8、編譯器可以隱式指定強(qiáng)制構(gòu)造函數(shù)

  因?yàn)榫幾g器可以隱式選擇強(qiáng)制構(gòu)造函數(shù),你就失去了調(diào)用函數(shù)的選擇權(quán)。如果需要控制的話,不要聲明只有一個(gè)參數(shù)的構(gòu)造函數(shù),取而代之,定義helper函數(shù)來負(fù)責(zé)轉(zhuǎn)換,如下面的例子:

  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. class Money  
  4. {  
  5.  public:  
  6.     Money();  
  7.     // Define conversion functions that can only be  
  8.     // called explicitly.  
  9.     static Money Convert( char * ch )  
  10.     { return Money( ch ); }  
  11.     static Money Convert( double d )  
  12.     { return Money( d ); }  
  13.     void Print() { printf( "%f", _amount ); }  
  14.  private:  
  15.     Money( char *ch ) { _amount = atof( ch ); }  
  16.     Money( double d ) { _amount = d; }  
  17.     double _amount;  
  18.    };  
  19.  
  20. void main()  
  21. {  
  22.  // Perform a conversion from type char *  
  23.  // to type Money.  
  24.  Money Account = Money::Convert( "57.29" );  
  25.  Account.Print();  
  26.  // Perform a conversion from type double to type  
  27.  // Money.  
  28.  Account = Money::Convert( 33.29 );  
  29.  Account.Print();  
  30. } 

  在上面的代碼中,強(qiáng)制構(gòu)造函數(shù)定義為private而不可以被用來做類型轉(zhuǎn)換。然而,它可以被顯式的調(diào)用。因?yàn)檗D(zhuǎn)換函數(shù)是靜態(tài)的,他們可以不用引用任何一個(gè)對(duì)象來完成調(diào)用。

  總結(jié)

  要澄清一點(diǎn)是,這里提到的都是我們所熟知的ANSI C++能夠接受的。許多編譯器都對(duì)ANSI C++進(jìn)行了自己的語法修訂。這些可能根據(jù)編譯器的不同而不同。很明顯,許多編譯器不能很好的處理這幾點(diǎn)。探索這幾點(diǎn)的緣故是引起編譯構(gòu)造的注意,也是在C++標(biāo)準(zhǔn)化的過程中移除一些瑕疵。

【編輯推薦】

  1. 程序員必看 c++筆試題匯總
  2. C++構(gòu)造函數(shù)如何進(jìn)行初始化
  3. 淺析C++中的C++構(gòu)造函數(shù)
  4. C#構(gòu)造函數(shù)概述
  5. 深度探討C++靜態(tài)構(gòu)造函數(shù)

 

責(zé)任編輯:韓亞珊 來源: 新云網(wǎng)絡(luò)
相關(guān)推薦

2013-01-14 09:29:04

2024-07-26 10:42:30

2011-05-10 10:38:54

布線光纖

2010-01-27 17:16:52

C++構(gòu)造函數(shù)

2017-01-12 14:26:30

2010-04-28 09:50:14

Oracle數(shù)據(jù)庫

2011-04-06 12:29:42

2011-08-17 12:25:11

2025-02-06 13:23:09

C++函數(shù)參數(shù)

2012-12-10 09:57:00

路由器交換機(jī)

2020-09-15 09:55:30

類比Python開發(fā)

2010-01-28 10:49:22

C++構(gòu)造函數(shù)

2023-11-28 11:51:01

C++函數(shù)

2011-03-22 14:59:36

2010-01-25 14:43:00

C++構(gòu)造函數(shù)

2010-01-25 17:05:37

C++語言

2024-01-25 11:36:08

C++構(gòu)造函數(shù)關(guān)鍵字

2009-08-13 17:30:30

C#構(gòu)造函數(shù)

2011-07-20 13:47:14

CC++

2010-01-22 11:13:16

C++靜態(tài)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

国产性天天综合网| 九色精品91| 亚洲自拍偷拍欧美| 国产自产在线视频一区| 精品人妻一区二区色欲产成人| 少妇高潮一区二区三区| 欧美日韩在线播放三区四区| 99视频精品全部免费看| 天天干视频在线| 日韩av一区二区三区四区| 久久人人爽人人爽爽久久| 国产精品福利导航| 日韩成人综合网站| 午夜视频一区在线观看| 五码日韩精品一区二区三区视频| 97人妻一区二区精品免费视频| 亚洲夜间福利| 色狠狠久久aa北条麻妃| 欧美xxxx黑人| 免费在线观看一区| 天天综合色天天| 一区二区三区免费看| 污污的视频网站在线观看| 久久爱www久久做| 韩国一区二区电影| 国精产品视频一二二区| 欧美理论电影在线精品| 91精品国产一区二区三区蜜臀| 每日在线更新av| 羞羞的视频在线看| 欧美激情一区在线观看| 国产精品免费一区二区三区在线观看| 欧美h在线观看| 国产综合欧美| 菠萝蜜影院一区二区免费| 强伦人妻一区二区三区| www.丝袜精品| 91精品国模一区二区三区| 三级4级全黄60分钟| 国内老司机av在线| 亚洲欧美一区二区三区久本道91 | 亚洲综合五月天婷婷丁香| 亚洲伊人观看| 欧美亚洲成人网| 国产精品1000| 亚洲精选国产| 欧美黑人性视频| 印度午夜性春猛xxx交| 四虎成人av| 色多多国产成人永久免费网站| 精品人妻互换一区二区三区| 日韩黄色网络| 亚洲精品国产欧美| 奇米777第四色| 国产精品115| 亚洲国产日韩一区| 污污污www精品国产网站| 99精品中文字幕在线不卡| 9999精品成人免费毛片在线看 | 国产精品久久久久四虎| 青青草国产精品| 韩国中文免费在线视频| 久久精品亚洲乱码伦伦中文| 日本欧美精品久久久| 狠狠v欧美ⅴ日韩v亚洲v大胸| 久久日韩精品一区二区五区| 欧美大陆一区二区| 国产在线自天天| 国产清纯白嫩初高生在线观看91 | 亚洲一区二区三区四区中文字幕 | 中文字幕一区日韩精品欧美| 日本在线高清视频一区| 国产在线电影| 国产精品久久久久久久岛一牛影视 | 日本日本19xxxⅹhd乱影响| 超碰高清在线| 亚洲福利一二三区| 日本人妻伦在线中文字幕| 好看的中文字幕在线播放| 精品日本美女福利在线观看| 国产av熟女一区二区三区| 啊啊啊久久久| 日本高清无吗v一区| 激情五月婷婷基地| 2020国产精品极品色在线观看| 精品国产伦一区二区三区观看体验| 极品白嫩的小少妇| 九热爱视频精品视频| 日韩综合中文字幕| 欧美性受xxxx| 高清无码视频直接看| 丰满的护士2在线观看高清| 欧美日韩久久久久| 向日葵污视频在线观看| 亚洲国产中文在线二区三区免| 亚洲成色777777在线观看影院| 人妻大战黑人白浆狂泄| 日韩欧美高清| 国模私拍一区二区三区| 日本精品入口免费视频| 国产高清精品网站| 欧美一级爱爱| 制服丝袜在线播放| 色妞www精品视频| 日本一本在线视频| 亚洲欧洲av| 欧美久久久精品| 国产熟妇一区二区三区四区| 国产精品77777| 欧美日韩国产综合视频在线| 制服丝袜中文字幕在线| 欧美这里有精品| 男男一级淫片免费播放| 日本欧美国产| 91精品国产91久久久久福利| 国产又粗又猛视频| 久久一区二区三区国产精品| 欧美 亚洲 视频| 国产91欧美| 亚洲欧美日韩网| 久久免费视频精品| 精品在线观看视频| 日本一区免费| av第一福利在线导航| 7777精品伊人久久久大香线蕉最新版| 亚洲熟妇一区二区三区| 黑人一区二区| 成人激情综合网| a黄色在线观看| 欧美日韩一区二区在线| 国产免费a级片| 亚洲成人tv| 国产精品最新在线观看| 邻家有女韩剧在线观看国语| 亚洲国产精品久久不卡毛片| 亚洲综合在线一区二区| 日韩精品一区二区三区免费观影| 57pao精品| 天堂av手机版| 亚洲国产aⅴ成人精品无吗| 天天av天天操| 亚洲男女av一区二区| 国产精品午夜视频| 福利视频在线导航| 在线观看91视频| 久久久久久国产精品无码| 在线视频精品| 久久精品99久久| 日韩伦理在线| 日韩电影中文字幕av| 日韩精品在线不卡| 99视频热这里只有精品免费| 久久99中文字幕| 国产欧美自拍一区| 91精品国产乱码久久久久久蜜臀| 熟妇人妻中文av无码| 亚洲高清视频在线| 性欧美成人播放77777| 亚洲欧美日韩国产一区| 久久久水蜜桃| 丝袜美腿一区| 色偷偷9999www| 国产又粗又猛又爽又黄91| 亚洲欧洲www| 小日子的在线观看免费第8集| 最新欧美人z0oozo0| 91亚色免费| a国产在线视频| 日韩高清欧美高清| 日本成人一级片| 一区在线观看视频| 色婷婷狠狠18禁久久| 亚洲小说区图片区| 麻豆91蜜桃| 成人福利片在线| 欧美精品一区在线播放| 日本高清视频免费看| 欧美日韩一区二区免费视频| 日本污视频网站| 国产成人一区二区精品非洲| 国产免费黄色av| 欧美一区二区三区高清视频| 91网站免费看| 精品丝袜在线| 色偷偷偷亚洲综合网另类| www.国产视频| 色综合久久久久久久久久久| 国产乱子轮xxx农村| 国产成人av一区二区三区在线观看| 热99这里只有精品| 色88久久久久高潮综合影院| 91精品国产综合久久久久久丝袜| 精品三级久久| 久久影院中文字幕| 日韩精品视频无播放器在线看 | 久久中文字幕一区| 香蕉视频成人在线| 欧美精品久久一区| 国产又爽又黄的视频| 中文字幕中文字幕在线一区| 人妻av一区二区三区| 日韩成人伦理电影在线观看| a级片一区二区| 日本午夜精品| 亚洲tv在线观看| 性欧美超级视频| 欧美国产日韩精品| 在线观看免费高清完整| 欧美精品一区二区高清在线观看| 波多野结衣在线电影| 亚洲韩国精品一区| av资源在线免费观看| 99re成人精品视频| 久久出品必属精品| 美女尤物国产一区| 两根大肉大捧一进一出好爽视频| 一区二区中文字| 性欧美精品一区二区三区在线播放| 超碰精品在线观看| 成人黄色在线免费| 97欧美成人| 日本国产欧美一区二区三区| 青春草免费在线视频| 这里只有精品在线播放| 日本视频在线观看一区二区三区| 宅男在线国产精品| 中文字幕欧美人妻精品| 黑人精品xxx一区| 精品视频在线观看免费| 《视频一区视频二区| 国产18无套直看片| 久久久久久久久免费| 欧美熟妇精品一区二区| 国产一区二区三区四| 男生操女生视频在线观看| 日本vs亚洲vs韩国一区三区二区 | 麻豆精品在线播放| 欧美 激情 在线| 亚洲一区不卡| 色欲色香天天天综合网www| 国产精品hd| 99亚洲国产精品| 午夜国产精品视频| 粉嫩av一区二区三区天美传媒| 久久亚洲在线| 影音欧美亚洲| 夜间精品视频| 永久免费网站视频在线观看| 日韩综合精品| 国产免费色视频| 综合一区二区三区| 超碰超碰超碰超碰超碰| 影音先锋久久| 怡红院av亚洲一区二区三区h| 99国产精品99久久久久久粉嫩| 人人妻人人澡人人爽欧美一区双 | 黄色片久久久久| 久久xxxx| 能在线观看的av网站| 日本视频中文字幕一区二区三区| 丁香婷婷激情网| 精品午夜一区二区三区在线观看| 久久久精品高清| 国产99久久久国产精品潘金网站| 久草福利在线观看| 成人激情校园春色| 性活交片大全免费看| 91色视频在线| 亚洲精品视频网址| 亚洲女子a中天字幕| 国产一级一片免费播放放a| 亚洲成人av中文| 日本熟女毛茸茸| 欧美精品视频www在线观看| 国产夫绿帽单男3p精品视频| 精品国产91久久久久久久妲己| 亚洲日本国产精品| 色妞一区二区三区| 俺来也官网欧美久久精品| 97视频在线观看播放| 欧美亚洲大片| 5566av亚洲| 蜜桃tv一区二区三区| 一区二区三区四区欧美日韩| 国产综合自拍| 男女无套免费视频网站动漫| 国产在线播精品第三| 黄色录像a级片| 国产精品久久99| 日韩欧美一区二区一幕| 欧美三级日韩三级国产三级| 性猛交xxxx乱大交孕妇印度| 亚洲欧美国产一本综合首页| 在线观看a视频| 91sa在线看| 国产在线不卡一区二区三区| 黄色91av| 亚洲破处大片| 人人干人人视频| 国产成人av在线影院| 大胸美女被爆操| 精品久久久久久国产91| 国产又粗又长视频| 日韩成人黄色av| 毛片在线视频| 国产91在线播放精品91| 日韩第一区第二区| 亚洲 日韩 国产第一区| av成人黄色| 中文字幕人妻熟女在线| 国产精品久久久久久久久动漫| 国产成人无码一区二区三区在线| 欧美精品在欧美一区二区少妇 | 久久激情视频免费观看| 九色porny自拍视频在线观看 | 九九热这里只有在线精品视| 麻豆精品蜜桃| 看高清中日韩色视频| 欧美区一区二| 久久精品一二三四| 国产精品免费视频网站| 99re这里只有精品在线| 亚洲激情在线观看| 手机在线免费看av| 91久久精品美女高潮| 日韩欧美视频在线播放| 成年人免费在线播放| www.一区二区| 国产精彩视频在线| 欧美va亚洲va| 污视频网站免费在线观看| 国产在线视频欧美| 不卡在线一区二区| 搡女人真爽免费午夜网站| 国产精品精品| 99久久久无码国产精品| 午夜啪啪免费视频| 蜜臀av性久久久久蜜臀aⅴ流畅 | 警花av一区二区三区| 亚洲欧美日韩国产成人综合一二三区 | 日本天堂网在线观看| 日韩你懂的电影在线观看| 国产不卡在线| 成人国产精品一区| 我不卡影院28| mm131国产精品| 国产精品久久三| 中文字幕日韩经典| 最新国产精品亚洲| 婷婷成人av| 老汉色影院首页| 国产精品一区一区三区| 欧产日产国产v| 精品日韩欧美一区二区| 香蕉久久aⅴ一区二区三区| 91在线短视频| 好看的日韩av电影| 黄色av网址在线观看| 色综合一个色综合亚洲| 国产九色在线| 成人av在线亚洲| 欧美国产高清| 国产黑丝一区二区| 欧美性猛交xxxx偷拍洗澡| 好男人免费精品视频| 国产欧美韩国高清| 天天综合久久| 精品1卡二卡三卡四卡老狼| 亚洲成a人在线观看| 日韩一区二区三区中文字幕| 国产不卡精品视男人的天堂| 日韩欧美自拍| 色欲欲www成人网站| 午夜久久久久久电影| 免费国产在线观看| 国产日本欧美视频| 亚洲午夜极品| 精品无人区无码乱码毛片国产| 欧美午夜寂寞影院| 污污片在线免费视频| 精品一区二区三区国产| 免费人成在线不卡| 免费在线观看日韩| 亚洲欧美日韩精品久久亚洲区 | 国产成人l区| 精品无码久久久久久久动漫| 日韩国产在线观看| 久草网站在线观看| 亚洲免费av片| 久久天堂久久| 少妇高潮喷水久久久久久久久久| 国产欧美日韩综合| 成人久久精品人妻一区二区三区| 欧美怡春院一区二区三区| 国产精品久久观看| 蜜桃传媒一区二区亚洲av| 91精品蜜臀在线一区尤物| 小视频免费在线观看| 免费看av软件| 久久影院午夜论|