在程序設計語言中,把一個標識符和另一個程序實體相聯係的過程稱為束定。程序設計語言中一個標識符的含義取決於這種束定。

類型檢查並不能決定一個操作將被怎樣執行,或者說,不能決定哪些代碼用於執行必須的操作,這是束定的任務。対於上麵的例子,為在運行時執行操作Move(),編譯器將把操作Mwe()束定到Rect::Move()的實現上。即:結果,程序執行上述函數所定義的操作,將對象myRect的數據成員X更新為10,Y更新為20。由於Move()是操作對象myRect,所以,在Move()的實禪中所引用的數據成員X和Y的含義就被束定到對象myRect的子對象上。如果對Rect的另一個對象(如:yourRect)執行操作Move(),那麼,成員函數Move()中所使用的標識符A和Y的含義表係的是對象yourRect的子對象。

應該記住,使用成員函數對一個對象所做的操作,就是對該對象數據成員的操作。成員函數的實現代碼表示了該對象的數據成員是怎樣被該成員函數一步步地訪問或更新的。

可見,像A和B都有自己不同的數據空間。此時,它們的數據成員X,Y,W,H都還沒有值。雖然由同一個類所建立對象的數據結構是相同的,但是A和B是兩個不同的對象,它們數據結構的內容(數據值)就有可能不同,對象的引用(名字)也不相同。

這兩條語句分別打印出對象A和對象B的麵積值。表達式A.Area()調用的是對象A的成員函數Area(),所以,A.AreaO是根據A的四個數據成員返回麵積值;而B.Area()是根據B的四個數據成員返回麵積值。

這兩條語句用來畫矩形,同理,表達式A.Dmw()是根據對象A的四個數據成員畫矩形,B.Area()是根據對象B的四個數據成員畫矩形。

需要說明的是:雖然對象A和B占據內存中的不同區域,並且它們所保存的數據也不同,但是,它們的成員函數代碼是一樣的。所以,為了節省內存,在創建對象A和B的時候,隻為它們各自分配用於保存數據的數據空間,而讓它們共享同一塊代碼空何。類中的代碼被放在內存的一個公共區域中,供該類的所有對象共享,這隻是Visual C++實現對象的一種方法。從我們用戶的角度看,仍要把對象理解成是由數據和代碼共同組成的。

四、成員函數(包括內聯成員函數)

這裏介紹幾種特殊的成員函數。我們在前麵學習過內聯函數、帶缺省值的函數和重載函數,如果把它們應用到成員函數上,即為內聯的成員函數、帶缺省值的成員函數和成員函數名重載。

1.內聯的成員函數。可以根據需要,將類中的一些成員函數聲明為內聯函數,而將其它的成員函數聲明為非內聯函數。有兩種方式可以使成員函數成為內聯函數。

方法一:通過關鍵字inline把它定義成內聯函數。

應該注意,對於使用inline關鍵字實現的內聯成員函數,對它的聲明必須在對它的調用之前。

方法二:在類的說明中,還可以直接定義成員函數。那麼該函數將被自動轉成內聯函數。這時,不必使用關鍵字inline。

顯然,本例和上例的效果是相同的。隻不過這種形式的內聯使類的聲明顯得不簡潔,所以我們提倡使用帶關鍵字的內聯函數。

2.帶有缺省值的成員函數和成員函數名重栽。在類中同樣可以.聲明帶有缺省值的函數和成員函數名重載。

5.2構造函數和析構函數

構造函數和析構函數是類中聲明的兩種特殊的成員函數,構造函數的作用是在對象被創建時使用特定的值構造對象。或者說將對象初始化為一個特定的狀態。而構函數完成時象被刪除前的一些清理工作。這些工作一般與構造函數所完成的工作的百的相反。

一、構造函數

一種常見的情況是,對象的某些部分在使用之前需要被初始化。例如,對於類Rect的對象,在調用成員函數Area()和Draw()之前,需要對數據成員X,Y,W,H進行防始化。以前我們是利用成員函數Move()和Size()來實現初始化操作的。這樣,每次郎要顯示地調用這兩個成員函數,很麻煩。那麼,我們能不能在創建對象時就自動進行初治化呢?構造函數就能完成這種初始化的工作。

構造函數是一種特殊的成員函數,與其它成員函數不同點在於:

1.構造函數必須和類同名,並且由用戶自行定義,這樣,編譯器才能辨別成員函數尹誰是構造函數。

2.不能為構造函數指定任何返回類型(包括void類型)。

3.當一個類定義好後,隻要以該類定義一個對象,則構造函數便會被自動調用(如果該類有構造函數),也就是說構造函數是由編譯器依情況自動調用,而不是通過用戶。

一般地,總是把構造函數定義成公有的。

在定義完上麵的構造函數以後,我們就可以這樣說明類Rect的對象了。

RedmyRect(10,20,100,200);

這樣,對象myRect被創建時,編譯器自動調用構造函數Rect(),並把myRect之後括號中的四個值作為實際參數傳遞給構造函數Rect(),從而使對象myRect的數據成員得到初始化。

對構造函數還有兩點說明:

1.在程序中,不能直接調用構造函數。調用構造函數就意味著建立一個對象,隻有在說明一個對象時,才能對構造函數進行調用。

2.構造函數的參數個數和類型規定了在聲明一個對象時,為這個對象進行初始化所需初始值的個數和類型。例如,如果要聲明一個Location類的對象,必須使用形式。

二、重栽構造函數

在一個類中,也可以聲明多個構造函數,隻要每個構造函數參數表中的參數個數或參數類型都各不相同。也就是說,可以重載構造函數。如果希望以多種方式初始化對象,如上例中的LocationA(10);和LocationA;重載構造函數是比較有用的。

例5.6重載構造函數Location,使它能接受LocationA(10);和LocationA;兩種形式的對象說明。

當執行語句LocationC(10,20)時調用構造函數Location(intxx,intyy)。

注意,在說明對象A時,LocationA;不能寫成LocationA();否則,編譯器會認為A是個函數名,該函數沒有參數,返回值是Location類型的對象。

三、缺省構造函數

在定義一個類時,並不是一定要定義構造函數的。如果在一個類中我們沒有定義任何構造函數,編譯器就會自動產生一個沒有參數的構造函數,即缺省構造函數。但是,編譯器自動產生的缺省構造函數的函數體為空,所以它什麼也不做。由於這種構造函數不初始化任何數據成員,它所聲明的對象也許是不安全的。所以,一般我們要在類中明確地給出自己的缺省構造函數,並讓它給類的數據成員賦缺省值。如上例中的構造函數Location()不帶任何參數,所以是缺省的構造函數。這個構造函數的作用是為敎據成員X和Y賦缺省值。