天天看點

《C++面向對象高效程式設計(第2版)》——3.2 類要素的細節include “IntStack.h”include “X.h” // 包含X類的聲明

本節書摘來自異步社群出版社《c++面向對象高效程式設計(第2版)》一書中的第3章,第3.2節,作者: 【美】kayshav dattatri,更多章節内容可以通路雲栖社群“異步社群”公衆号檢視。

c++面向對象高效程式設計(第2版)

3.2.1 通路區域

客戶可以通路在類的<code>public</code>區域中聲明的任何成員。我們可以把該區域看做是通用公共(<code>general public</code>)的接口,它沒有任何保護,是類限制最少的區域。一個設計良好的類絕不會将資料成員包含在<code>public</code>區域,該區域隻能包含成員函數。如果在public區域包含資料成員,那麼無需類的實作者,僅通過編譯器即可通路這些資料成員。這違反了資料抽象和封裝原則。這也是我們為什麼總将資料成員放在<code>private</code>或<code>protected</code>區域的原因。

smalltalk:

在smalltalk中,類絕不能包含公有執行個體變量,隻有方法才能設定為公有。這樣規定的目的是,隻有類實作才有權通路執行個體變量。客戶需要調用方法,才能獲得和設定執行個體變量的值。

注意:

允許客戶設定對象中的資料成員值的方法,通常稱為設值方法(<code>setter</code>)。用于傳回資料成員值的方法稱為獲值方法(<code>getter</code>)。

eiffel:

在eiffel中,類沒有任何限制,可以導出(<code>export</code>)任何成員函數和資料成員。但是,客戶隻能通路卻不能修改導出的資料成員。換言之,客戶對導出的資料成員隻有隻讀通路權限。另外,通過導出的成員名無法識别是資料成員還是成員函數。這和<code>pacsal</code>類似,調用無參數的函數看上去像是對某變量的引用。

回到c++中,相對于public區域的另一個極端區域是private區域。成員函數的實作可以通路在類中聲明的所有成員(也就是說,類的成員函數可以通路類作用域内的任何成員)。是以,編寫類成員函數的程式員就是類的實作者。類的普通使用者無法操控private區域,使用者對private區域知道得越少越好。不言自明,如果某程式能通路private區域的成員,它也能通路類中的其他成員(包括public和protected區域)。實際上,c++在設計通路控制時很奇怪,一方面允許“看見”私有資料成員的聲明;另一方面又不允許公共客戶通路它們。

<code>protected</code>區域的限制比<code>private</code>區域寬松,但比<code>public</code>區域嚴格。protected區域用于給派生類(通過繼承)使用,後面的章節将作詳細介紹。如果客戶能通路<code>protected</code>區域,也能通路<code>public</code>區域。

類可以包含多個<code>public,private</code>和<code>protected</code>區域,c++對這些區域的數量沒有限制。任何區域都可以包含成員函數和資料成員。在類的不同區域中聲明的任何成員(資料或函數)将獲得相應聲明區域的通路規則。

構造函數:構造函數是特殊的成員函數。它無傳回值,而且不能是const或static成員函數。類可以包含任意數量的重載構造函數。

在建立對象時,會調用構造函數。可以通過多種方式建立類的對象,如下所列:

tintstack::tintstack(unsigned int stacksize / = default_size /)

{

  // 隻有stacksize 大于0時,才配置設定記憶體。

  if (stacksize &gt; 0) {

    _size = stacksize;

    _sp = new int[_size]; // 為stack的元素配置設定記憶體

    // 将所有元素都初始化為0

    for (int i = 0; i &lt; _size; i++)

       _sp[i] = 0;

   }

   else {

      _sp = 0; // 為指針設定獨特的值(_unique value_)

      _size = 0;

   _count = 0; // 棧中無元素

}<code>`</code>

調用構造函數時,隻建立了一個空對象,其中的資料成員包含無用單元(garbage)。這些資料成員就像是未初始化的自動變量,我們必須正确地初始化它們。通過檢查以确認客戶請求的棧的大小為正整數,然後使用new()操作符配置設定記憶體,用合适的值初始化所有的資料成員。這些就是需要在構造函數中完成的工作。

警告:

如果将x類聲明為:

main()

      x alpha; // 建立一個x類的對象alpha

        x b(10); // 建立另一個對象 b

為對象alpha調用哪一個構造函數?我們可以認為調用了上面的⑨,因為它不需要傳遞任何參數。但是,也可以在函數沒有參數的情況下調用⑧,這裡存在沖突。[ 編譯器一旦遇到諸如x類這樣的構造函數聲明,會立即标記出來。] 是以,當x.h進行編譯時,将會報錯,迫使x的實作者解決這個問題。這稱為聲明時錯誤檢測(error detection at the point of declaration),錯誤一出現它就馬上檢測出來(即在x.h自身進行編譯時)。然而,某些編譯器直到使用這些構造函數時才報錯(即在編譯客戶代碼時才會檢測出來)。這稱為使用時錯誤檢測(error detection at the point of use)。但是客戶無法修複這個錯誤,因為他沒有(或無權操控)x類的代碼。我們隻能希望随着c++編譯器日趨成熟,這樣的問題在所有的編譯器中都能得到改善。

本文僅用于學習和交流目的,不代表異步社群觀點。非商業轉載請注明作譯者、出處,并保留本文的原始連結。

繼續閱讀