程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 深度探索C++對象模型(4)

深度探索C++對象模型(4)

編輯:C++入門知識
  雷神跌跌撞撞的讀完了《深度探索C++對象模型》的第一章,雖然還是有些迷惑,但是已經感到收獲很大。按照朋友的說法,第一章是一個概括的介紹,具體的細節會在以後的章節闡述,假如沒有通讀本書,第一章還是比較不輕易理解的。 <!-- frame contents --> <!-- /frame contents --> 雷神聽過之後信心倍增,也不在有初看此書時的“世界末日”的感覺了(在第2篇雷神感到學了近一年的C++,居然水平如此之差),並且通過自己的努力,還是摸到了些門道,所以讓我們繼續快樂的出發,踏上深度探索C++對象模型的旅程。記住我們在第一篇的小文《堅持不懈,直到成功》,這可是獲得成功的不二法門。
  
  第二章主要講的的構造函數語意(Semantics),這是一個什麼意思?我的英文和中文學的都不好,但我想是書上弄錯了(也許只是一個筆誤),也許應該翻譯成語義比較恰當。The study or science of meaning in anguage forms. 語義學以語言形式表示意思的研究或科學。我們要研究構造函數的,並且以語言的形式將它描述清楚。   看完題目我的第一個感覺,構造函數我知道。構造函數是一個類的成員函數,構造函數和析構函數是進行對象數據的創建,初始化,清除工作的成員函數,可以重載構造函數,使一個類不止具備一個構造函數,因有時需要以這些方法中的某一種分別創建不同的對象。不能重載析構函數。構造函數作為成員函數和類有相同的名字。例:一個類名為:aClass,構造函數就是aClass()。構造函數沒有返回值,而且不能定義其返回類型,void也不行。析構函數同樣使用這一點。當編寫重載函數時,只有參數表不同,通過比較其參數個數或參數類型可以區分兩個重載函數。但是我讀完第一小段後就知道這一章要告訴我們什麼了。
  
  這一章並不是要告訴我們什麼是構造函數,它的作用是什麼。而是要告訴我們的是構造函數是如何工作的。我的。在得知這點後我很興奮,因為我確實不知道構造函數是如何構造一個類的對象的,並且一直想知道。我一直對面向對象神奇的功能很感愛好。為什麼一個類在被實例化時,可以自動的完成很多工作,使我們的主函數清楚,簡單,穩健,高效。以前只看到了表面,沒有深入,這會我們有機會去皮剔肉深入骨髓了。 書上主要討論了幾種情況:
  
  帶有缺省構造函數的成員對象。假如一個類沒有任何的構造函數,但他有一個成員對象,這個對象的類有一個缺省的構造函數,那麼編譯器會在需要的時候為這個類合成一個構造函數。
  
  舉個例子:
  
  我們有以下幾個類。它們都有一個構造函數。
   貓{public:貓(),......};
  狗{public:狗(),......};
  鳥{public:鳥(),......};
  魚{public:魚(),......};   我們又有一個類。寵物,我們將貓作為它的成員之一。並且沒有給它聲明構造函數。
   寵物{
  public:
  貓 一只貓;
  狗 一只狗;
  鳥 一只鳥;
  魚 一只魚;
  private:
  int ival;
  ......
  }   則當需要的時候編譯器會為它合成一個構造函數,並且采用內聯方式。大概象下面的樣子。
   inline
  寵物::寵物()
  {
  貓.貓::貓();
  狗.狗::狗();
  鳥.鳥::鳥();
  魚.魚::魚();
  ival=0;
  }   為什麼會這樣,我們來看看編譯器的行動。編譯器開始執行用戶的代碼,預備生成寵物對象之前,會首先調用必要的構造函數,來初始化類的成員,以便為對象分配合適的內存空間。結果編譯器會合成上面的構造函數,假如程序員為寵物類寫了一個構造函數。 寵物::寵物(){ival=0;}那編譯器也會將這個構造函數擴張成上面的那樣。編譯器是怎樣實現的呢?原來當一個類沒有任何用戶定義的構造函數,而是由編譯器自動生成的話,則這個被暗中生成的構造函數將會是一個沒有什麼用處的構造函數。但是通過編譯器的工作能夠為我們合成一個nontrivial default constrUCtor.
  
  好象香港電影中演的,假如你惹上官司(你要設計一個類),你又沒有錢去請高級的律師(沒有給出構造函數),那會給你分配一個律師(缺省的構造函數),當然這個律師的能力也許和那些大律師比起來有差距(trivial)。不過我們要知道他們也不是一點用都沒有。但是由於有律師行的督導,可以使這些律師能夠努力做到最好(nontrivial)。   同樣的道理,我們可以理解另外的幾種nontrivial default constructor的情況。
  
  假如你的類沒有任何的構造函數,並且它派生於一個有著缺省構造函數的基類,那這個派生類的缺省構造函數會被視為nontrivial,因此需要被合成出來,他的合成步驟是調用上一層基類的缺省構造函數,並根據它們的聲明次序為派生類合成一個構造函數。   假如類聲明或繼續了一個虛函數,或者類派生於一個繼續串鏈,其中有一個或更多的虛擬基類。由於缺少使用者聲明的構造函數,則編譯器會合成一個缺省的構造函數,以便正確的初始化每一個類對象的vptr。   最後說一點,在合成的缺省構造函數中,只有基類的子對象和類的成員對象會被初始化,所有其他的非靜態數據成員都不會被初始化,因為這些操作是需要程序員來做的。編譯器沒有必要連這些工作都做了。 好了,這篇就寫到這裡吧。這本書真的是雷神所看過的書中,看的最慢的一本了。但這些深層的知識有必要了解的很清楚嗎,我們不知道編譯器如何合成缺省的構造函數不也能寫程序嗎?雷神用侯大師的話往返答這個問題:練從難處練,用從易處用。
   知其然而不知其所以然,不是一個嚴謹的學習態度。
 
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved