1. 程式人生 > >C++類與對象(05)

C++類與對象(05)

系統 描述 預處理 運行時 對象共享 logs 私有 有意 文件包含

類是具有惟一標識符的實體;在類中聲明的任何成員不能使用extern、auto和register關鍵字進行修飾;類中聲明的變量屬於該類,在某些情況下,變量也可以被該類的不同實例所共享。

訪問權限用於控制對象的某個成員在程序中的可訪問性,如果沒有使用關鍵字,則所有成員默認聲明為private權限。

定義成員函數

類中聲明的成員函數用來對數據成員進行操作,還必須在程序中實現這些成員函數。 定義成員函數的一般形式如下:

返回類型 類名::成員函數名(參數列表) { 成員函數的函數體//內部實現 }

其中“::”是作用域運算符,“類名”是成員函數所屬類的名字,“::”用於表名其後的成員函數是屬於這個特定的類。換言之,“類名::成員函數名”的意思就是對屬於“類名”的成員函數進行定義,而“返回類型”則是這個成員函數返回值的類型。 也可以使用關鍵字inline將成員函數定義為內聯函數。 如果在聲明類的同時,在類體內給出成員函數的定義,則默認為內聯函數。

數據成員的賦值

不能在類體內給數據成員賦值。在類體外就更不允許了。 數據成員的具體值是用來描述對象的屬性的。只有產生了一個具體的對象,這些數據值才有意義。如果在產生對象時就使對象的數據成員具有指定值,則稱為對象的初始化

使用類的對象

對象和引用都使用運算符“.”訪問對象的成員,指針則使用“- >”運算符。

(1)類的成員函數可以直接使用自己類的私有成員(數據成員和成員函數)

(2)類外面的函數不能直接訪問類的私有成員(數據成員和成員函數)

(3)類外面的函數只能通過類的對象使用該類的公有成員函數。

在程序運行時,通過為對象分配內存來創建對象。在創建對象時,使用類作為樣板,故稱對象為類的實例。

定義類對象指針的語法如下:

類名* 對象指針名;

對象指針名=對象的地址;

也可以直接進行初始化。

類名* 對象指針名=對象的地址;

類對象的指針可以通過“->”運算符訪問對象的成員,即: 對象指針名->對象成員名

數據封裝

面向對象的程序設計是通過為數據和代碼建立分塊的內存區域,以便提供對程序進行模塊化的一種程序設計方法,這些模塊可以被用做樣板,在需要時在建立其副本。根據這個定義,對象是計算機內存中的一塊區域,通過將內存分塊,每個模塊(即對象)在功能上保持相對獨立。 對象被視為能做出動作的實體,對象使用這些動作完成相互之間的作用。換句話說,對象就像在宿主計算機上擁有數據和代碼並能相互通信的具有特定功能的一臺較小的計算機。

運算符new

運算符new用於建立生存期可控的對象,new返回這個對象的指針。由於類名被視為一個類型名,因此,使用new建立動態對象的語法和建立動態變量的語法類似,其不同點是new和構造函數一起使用。使用new建立的動態對象只能用delete刪除,以便釋放所占空間。應養成及時釋放不再使用的內存空間的習慣。

賦值構造函數

編譯器建立一個默認復制構造函數,默認復制構造函數采用拷貝方式使用已有的對象來建立新對象,所以又直譯為拷貝構造函數。程序員可以自己定義復制構造函數,對類A而言,復制構造函數的原型如下:

A::A(A&)  

從這個函數原型來看,首先它是一個構造函數,因為這畢竟是在創造一個新對象。其次,他的參數有些特別,是引用類自己的對象,即用一個已有的對象來建立新對象。使用引用是從程序的執行效率角度考慮的。為了不改變原有對象,更普通的形式是像下面這樣使用const限定: A::A(const A &)

析構函數

在對象消失時,應使用析構函數釋放由構造函數分配的內存。構造函數、賦值構造函數和析構函數是構造型成員函數的基本成員,應深刻理解他們的作用並熟練掌握其設計方法。

調用析構函數也是由編譯器來完成的,所以編譯器必須總能知道應調用哪個函數。最容易、也最符合邏輯的方法是指定這個函數的名稱與類名一樣。為了與析構函數區分,在析構函數的前面加上一個“~”號(仍然稱析構函數與類同名)。在定義析構函數時,不能指定任何返回類型,即使指定void類型返回類型也不行。析構函數也不能指定參數,但是可以顯示地說明參數為void,即形如A::~A(void)。從函數重載的角度分析,一個類也只能定義一個析構函數且不能指明參數,以便編譯系統自動調用。

析構函數在對象生存期結束時被自動調用。當對象的生存期結束時,程序為這個對象調用析構函數,然後回收這個對象占用的內存。全局對象和靜態對象的析構函數在程序運行結束之前調用。 類的對象數組的每個元素調用一次析構函數。全局對象數組的析構函數在程序結束之前被調用。

析構函數與運算符delete

運算符delete與析構函數一起工作。當使用運算符delete刪除一個動態對象時,他首先為這個動態對象調用析構函數,然後再釋放這個動態對象占用的內存,這和使用new建立動態對象的過程正好相反。

當使用delete釋放動態對象數組時,必須告訴這個動態對象數組有幾個元素對象,C++使用“[ ]”來實現。即語句 delete[ ] ptr

當程序先後創建幾個對象時,系統按後建先析構的原則析構對象。當使用delete調用析構函數時,則按delete的順序析構。

默認析構函數

如果在定義類時沒有定義析構函數,C++編譯器也為它產生一個函數體為空的默認析構函數。

this指針

使用this指針,保證了每個對象可以擁有自己的數據成員,但處理這些數據成員的代碼可以被所有的對象共享。

C++規定,當一個成員函數被調用系統自動向它傳遞一個隱含的參數,該參數是一個指向調用該函數的對象的指針,從而使成員函數知道該對哪個對象進行操作。在程序中,可以使用關鍵字this來引用該指針。this指針是C++實現封裝的一種機制,它將對象和該對象調用的成員函數連接在一起,在外部看來,每一個對象都擁有自己的成員函數。

除非有特殊需要,一般情況下都省略符號“this ->”,而讓系統進行默認設置。

對象的性質

(1)同一個類的對象之間可以相互賦值。

(2)可使用對象數組。

(3)可使用指向對象的指針使用取地址運算符&將一個對象的地址置於該指針中。 註意,指向對象的指針不能取數據成員的地址,也不能去成員函數的地址

(4)對象可以用作函數參數。對象作為函數參數時,可以使用對象、對象引用和對象指針。

(5)一個對象可以做為另一個類的成員。

類的性質

使用類的權限

數據成員為私有,成員函數為公有的情況:

(1)類本身的成員函數可以使用類的所有成員(私有和公有成員)。

(2)類的對象只能訪問公有成員函數。

(3)其他函數不能使用類的私有成員,也不能使用公有成員函數,它們只能通過類的對象使用類的公有成員函數。

(4)雖然一個可以包含另外一個類的對象,但這個類也只能通過被包含類的對象使用那個類的成員函數,通過成員函數使用數據成員。

面向對象編程的文件規範

一般要求將類的聲明放在頭文件中,非常簡單的成員函數可以在聲明中定義(默認內聯函數形式),實現放在.cpp文件中。在.cpp文件中,將頭文件包含進去。主程序單獨使用一個文件,這就是多文件編程規範。

C++的源程序可包含各種編譯指令,以指示編譯器對源代碼進行編譯之前先對其進行預處理。所有的編譯指令都以#開始,每條編譯指令單獨占用一行,同一行不能有其他編譯指令和C++語句(註釋例外)。編譯指令不是C++的一部分,但擴展了C++編程環境的使用範圍,從而改善程序的組織和管理。

嵌入指令:

#include指示編譯器將一個源文件嵌入到帶有#include指令的源文件中該指令所在的位置處。尖括號或雙引號中的文件名可包含路徑信息。例如: #include<\user\prog.h> 註意:由於編譯指令不是C++的一部分,因此,在這裏表示反斜杠時只使用一個反斜杠。

宏定義:

#define指令定義一個標識符字符串,在源程序中每次遇到該標識符時,編譯器均用定義的字符串代替之。該標識符稱為宏名,而將替換過程稱之為宏替換。#define指令用以進行宏定義,其一般形式如下: #define 宏名 替換正文 ,“宏名”必須是一個有效的C++標識符,“替換正文”可為任意字符組成的字符序列。“宏名”和“替換正文”之間至少有一個空格。註意,宏定義由新行結束,而不以分號結束。如果給出了分號,則它也被視作為替換正文的一部分。當替換正文要書寫在多行上時,除最後一行外,每行的行尾要加上一個反斜線,表示宏定義繼續到下一行。 因宏定義有許多不安全因素,對需要使用無參數宏的場合,應該盡量使用const代替宏定義。 在程序的一個地方定義的宏名,如果不想使其影響到程序的其他地方,可以在不再使用時用#undef刪除

條件編譯指令:

條件編譯指令是#if、#else、#elif和#endif,它們構成類似於C++的if選擇結構,其中#endif表示一條指令結束。 編譯指令#if用於控制編譯器對源程序的某部分有選擇地進行編譯。該部分從#if開始,到#endif結束。如果#if後的常量表達式為真,則編譯這部分,否則就不編譯該部分,這時,這部分代碼相當於被從源文件中刪除。 編譯指令#else在#if測試失效的情況下建立另外一種選擇。可以在#else分支中使用編譯指令#error輸出出錯信息。#error使用的形式如下: #error 出錯信息 “出錯信息”是一個字符序列。當遇到#error指令時,編譯器顯示其後面的“出錯信息”,並中止對程序的編譯。 編譯指令可嵌套,嵌套規則和編譯器對其的處理方式與C++的if預計嵌套情況類似。

define操作符

關鍵字defined不是指令,而是一個預處理操作符,用於判斷一個標識符是否已經被#define定義。如果標識符identifier已被#define定義,則defined(identifier)為真,否則為假。 條件編譯指令#ifdef#ifndef用於測試其後的標識符是否被#define定義,如果已經被定義,則#ifdef測試為真,#ifndef測試為假;如果沒有被定義,則#ifdef測試為假,#ifndef測試為真。

在頭文件中使用條件編譯

C++類與對象(05)