本文聯(lián)合編輯:小辣辣。向她致以最崇高的敬(愛)意 ?
第一章 C++的初步認(rèn)識(shí)
在程序進(jìn)行編譯時(shí),先對(duì)所有的預(yù)處理命令進(jìn)行處理得院,將頭文件的具體內(nèi)容代替 #include
指令,然后再對(duì)該程序單元進(jìn)行整體編譯。
對(duì)函數(shù)做聲明阴汇,它的作用是通知 C++ 編譯系統(tǒng)。
第二章 數(shù)據(jù)的存儲(chǔ)节槐、表示形式和基本運(yùn)算
C++ 沒有規(guī)定每一種數(shù)據(jù)所占的字節(jié)數(shù)鲫寄,只規(guī)定 int 型數(shù)據(jù)所占的字節(jié)數(shù)不大于 long 型,不小于 short 型疯淫。
符號(hào)常量
#define PRICE 30
符號(hào)常量雖有名字地来,但它不是變量。在進(jìn)行編譯預(yù)處理時(shí)熙掺,所有的 PRICE 都被置換為字符 30未斑,在正式進(jìn)行編譯時(shí)已經(jīng)沒有 PRICE 這個(gè)標(biāo)識(shí)符了。但 C++ 程序員一般更喜歡用 const 定義常變量币绩。
運(yùn)算符
/
除法運(yùn)算符
結(jié)果是整數(shù)蜡秽,如果有一個(gè)是負(fù)數(shù),則舍入方向是不固定的缆镣。多數(shù)編譯系統(tǒng)采取向零取整的方法%
模運(yùn)算符
兩側(cè)均應(yīng)為整型數(shù)據(jù)芽突,如 7%4 的值為 3
+,–董瞻,*寞蚌,/ 運(yùn)算中的兩個(gè)數(shù)中有一個(gè)數(shù)為 float 型數(shù)據(jù),則運(yùn)算結(jié)果是 double 型钠糊,因?yàn)?C++ 在運(yùn)算時(shí)對(duì)所有 float 型數(shù)據(jù)都按 double 型數(shù)據(jù)處理挟秤。
進(jìn)行運(yùn)算時(shí),不同類型的數(shù)據(jù)都要先轉(zhuǎn)換成同一類型抄伍,然后進(jìn)行運(yùn)算艘刚。
自增(減)運(yùn)算符
也用于指針變量,使指針指向下一個(gè)地址截珍。
賦值運(yùn)算符和賦值表達(dá)式
賦值過程中的類型轉(zhuǎn)換
將浮點(diǎn)型數(shù)據(jù)賦值給整型變量時(shí)攀甚,舍棄其小數(shù)部分。
不同類型的整型數(shù)據(jù)間的賦值歸根到底就是一條:按存儲(chǔ)單元中的存儲(chǔ)形式直接傳送岗喉。
程序初步設(shè)計(jì)
關(guān)系運(yùn)算和邏輯運(yùn)算
運(yùn)算符優(yōu)先級(jí):
算數(shù)運(yùn)算符 > 關(guān)系運(yùn)算符 >賦值運(yùn)算符
在 C 和 C++ 中都用數(shù)據(jù) 1 代表真秋度,0 代表假。編譯系統(tǒng)在處理邏輯型數(shù)據(jù)時(shí)沈堡,將 false 處理為 0静陈,將 true 處理為 0。邏輯變量在內(nèi)存中占 1 個(gè)字節(jié),用來存放 0 或 1鲸拥。
用 for 語句構(gòu)成循環(huán)
for(表達(dá)式1拐格;表達(dá)式2;表達(dá)式3)語句
表達(dá)式 1 可以省略刑赶,但其后得分號(hào)不可省略捏浊。
如果表達(dá)式 2 省略,即不判斷循環(huán)條件撞叨,循環(huán)無休止地進(jìn)行下去金踪。
第四章 利用函數(shù)實(shí)現(xiàn)指定的功能
函數(shù)參數(shù)和函數(shù)的值
在調(diào)用函數(shù)時(shí),編譯系統(tǒng)臨時(shí)給形參分配存儲(chǔ)單元牵敷。調(diào)用結(jié)束后胡岔,形參單元被釋放,實(shí)參單元仍保留并維持原值枷餐。因此靶瘸,在執(zhí)行一個(gè)被調(diào)用函數(shù)時(shí),形參的值如果發(fā)生改變毛肋,并不會(huì)改變主調(diào)用函數(shù)中實(shí)參的值怨咪。
對(duì)被調(diào)用函數(shù)的聲明和函數(shù)原型
在函數(shù)聲明中可以不寫形參名,只寫形參類型
內(nèi)置函數(shù)(內(nèi)聯(lián)函數(shù))
轉(zhuǎn)去被調(diào)用函數(shù)前润匙,要記下當(dāng)時(shí)執(zhí)行的指令的地址诗眨,還要記下當(dāng)時(shí)有關(guān)的信息,以便在函數(shù)調(diào)用后繼續(xù)執(zhí)行孕讳,如果有的函數(shù)需要頻繁使用匠楚,則所用時(shí)間會(huì)很長(zhǎng),從而降低執(zhí)行效率卫病∮推。可以使用內(nèi)置函數(shù)將所調(diào)用的函數(shù)的代碼直接嵌入到主調(diào)函數(shù)中典徘,而不是將流程轉(zhuǎn)出去蟀苛。使用關(guān)鍵字 inline。
函數(shù)模板
template < typename T > //類似 Java 的泛型
有默認(rèn)參數(shù)的函數(shù)
注意點(diǎn):如果函數(shù)的定義在函數(shù)調(diào)用之前逮诲,則應(yīng)在函數(shù)定義中給出默認(rèn)值帜平。如果函數(shù)的定義在函數(shù)調(diào)用之后,則在函數(shù)調(diào)用之前需要有函數(shù)聲明梅鹦,此時(shí)必須許多函數(shù)聲明中給出默認(rèn)值裆甩,函數(shù)定義時(shí)可以不給出默認(rèn)值。
變量的存儲(chǔ)類型
-
auto(默認(rèn))
自動(dòng)變量齐唆,動(dòng)態(tài)局部變量嗤栓,函數(shù)調(diào)用結(jié)束后釋放
-
static
靜態(tài)局部變量在靜態(tài)存儲(chǔ)區(qū)內(nèi)分配存儲(chǔ)單元,在程序整個(gè)運(yùn)行期間都不釋放。
加上 static 聲明茉帅,則該變量只能用于本文件 -
register
寄存器變量叨叙,如果有一些變量使用頻繁,則為存取變量的值要花不少時(shí)間堪澎,為提高效率擂错,C++ 允許將局部變量的值放在 cpu 的寄存器中
-
extern
全局變量(外部變量),作用域從變量的定義開始樱蛤,到本程序文件的末尾
注意 extern 是用作變量聲明钮呀,而不是變量定義。它只是對(duì)一個(gè)已定義的外部變量做聲明昨凡,以擴(kuò)展其作用域爽醋。
內(nèi)部函數(shù)和外部函數(shù)
外部函數(shù)
如果在函數(shù)的首部的最左端冠以關(guān)鍵字 extern
,則表示此函數(shù)是外部函數(shù)便脊,可供其他文件調(diào)用子房。
第五章 利用數(shù)組處理批量數(shù)據(jù)
一維數(shù)組的初始化
- 可以只給一部分元素賦值(后面的元素默認(rèn)為 0)
- 對(duì)全部數(shù)組元素賦初值時(shí),可以不指定數(shù)組長(zhǎng)度
二維數(shù)組的初始化
- 可以對(duì)部分元素賦值
用數(shù)組作函數(shù)參數(shù)
數(shù)組名作實(shí)參和形參就轧,傳遞的是數(shù)組的起始地址证杭。
數(shù)組名代表數(shù)組首元素的地址。
用數(shù)組名作實(shí)參妒御,如果改變了形參數(shù)組元素的值將同時(shí)改變實(shí)參數(shù)組元素的值解愤。
字符數(shù)組
定義和初始化字符數(shù)組
如果提供的初值個(gè)數(shù)大于數(shù)組長(zhǎng)度,則按語法錯(cuò)誤處理乎莉。如果小于數(shù)組長(zhǎng)度送讲,則只將字符賦值給數(shù)組中前面的元素,其余的元素自動(dòng)定義為空字符 \0
字符數(shù)組的賦值和引用
只能對(duì)字符數(shù)組的元素賦值惋啃,而不能用賦值語句對(duì)整個(gè)數(shù)組賦值哼鬓。
結(jié)束標(biāo)志
遇到字符 \0
就表示字符串到此結(jié)束。對(duì)于一個(gè)字符串常量边灭,系統(tǒng)會(huì)自動(dòng)在所在字符的后面加一個(gè) \0
作為結(jié)束符异希,然后再把它存在字符數(shù)組中。
可以用字符串常量來初始化字符數(shù)組绒瘦。
字符數(shù)組的輸入和輸出
- 輸出得字符不包含結(jié)束符
\0
字符串處理函數(shù)
比較函數(shù) strcmp
strcmp(str1称簿,str2)
對(duì)兩個(gè)字符串自左至右逐個(gè)字符相比(按 ASCII 值大小比較)
兩個(gè)字符串比較,不能用以下形式:
if(str1 > str2) {
...
}
上面寫法表示將兩個(gè)數(shù)組的地址進(jìn)行比較惰帽。
字符串變量的定義和引用
和其他類型變量一樣憨降,字符串變量必須先定義后使用。
第六章 善于使用指針和引用
i_pointer
是一個(gè)指針變量该酗,* i_pointer
表示 i_pointer 所指向的變量授药。
*
不是指針變量名的一部分,在變量名前加一個(gè) *
表示該變量是指針變量。
不能用一個(gè)整數(shù)給指針變量賦值悔叽。
int * pointer = 2000;
編譯系統(tǒng)并不把 2000 認(rèn)為是地址航邢,而認(rèn)為是整數(shù)〗居可以將一個(gè)已定義的變量的地址作為指針變量的初值膳殷。
一個(gè)指針只能指向同一個(gè)類型的變量。
引用指針變量
&
: 取地址運(yùn)算符
&a
為變量 a 的地址九火, *p
為指針變量 p 所指向的存儲(chǔ)單元
int * pointer = & a //定義指針變量
pointer:指針變量
* pointer
等效于 a(對(duì)指針變量 pointer 做 *
運(yùn)算赚窃,指向 pointer 指向的存儲(chǔ)單元,即 a)
&
和 *
兩個(gè)運(yùn)算符的優(yōu)先級(jí)別相同岔激,但按自右而左方向結(jié)合勒极。例如已知 pointer = &a
,& * pointer
的含義是:先進(jìn)行 *pointer
的運(yùn)算虑鼎,它就是變量 a辱匿,再執(zhí)行 &
運(yùn)算,因此 & * pointer
與 & a
相同炫彩,即變量 a 的地址匾七。
用指針作函數(shù)參數(shù)
int main() {
void swap(int * p1, int * p2)
int * pointer_1, * pointer_2, a, b;
cin >> a >> b;
pointer_1 = &a;
pointer_2 = &b;
swap(pointer_1, pointer_2)
}
void swap(int * p1, int * p2) { //定義指針變量 p1, p2,即 swap 的形參須是指針
int temp;
temp = * p1; // * p1:對(duì)指針變量做 * 運(yùn)算江兢,指向值
...
}
不能試圖通過改變形參指針變量的值而使實(shí)參指針變量的值改變昨忆。實(shí)參和形參之間的數(shù)據(jù)傳遞是單向的“值傳遞”的方式,指針變量作函數(shù)參數(shù)也要遵循這一規(guī)則杉允,調(diào)用函數(shù)時(shí)不會(huì)改變實(shí)參指針變量的值邑贴,但可以改變實(shí)參指針變量指向變量的值。
int main(int argc, char* argv[])
{
void myswap(int * p1, int * p2);
int * point1, * point2, a, b;
a = 10, b = 20;
point1 = &a;
point2 = &b;
cout<<"a"<<a<<"b"<<b<<endl;
if(a < b) myswap(point1, point2);
cout<<"a"<<a<<"b"<<b<<endl;
if(a < b) realswap(point1, point2);
cout<<"a"<<a<<"b"<<b<<endl;
return 0;
}
//指針變量也是值傳遞叔磷,形參修改并不影響實(shí)參 point1 指針
void myswap(int * p1, int * p2) {
int * temp;
temp = p1;
p1 = p2;
p2 = temp;
}
void realswap(int * p1, int * p2) {
int temp;
temp = * p1;
* p1 = * p2; //* p1拢驾,直接修改 p1 指向的值(a)的值
* p2 = temp;
}
//輸出
a10b20
a10b20
a20b10
//分析
point1 = & a
* point1 即 point1 所指向的變量
數(shù)組和指針
指向數(shù)組元素的指針
int a[10]; //定義一個(gè)數(shù)組,有 10 個(gè)元素
int *p;
p = &a[0] //將元素 a[0] 的地址賦給指針變量 p改基,使 p 指向 a[0]
在 C++ 中繁疤,數(shù)組名代表數(shù)組中的第 1 個(gè)元素(即序號(hào)為 0 的元素)的地址,因此以下語句等價(jià):
p = &a[0];
p = a;
數(shù)組名 a 不代表整個(gè)數(shù)組寥裂,p=a
的作用是把 a 數(shù)組的首元素的地址賦給指針變量 p嵌洼。
如果指針變量 p 已指向數(shù)組中的一個(gè)元素,則 p + 1 指向同一個(gè)數(shù)組中的下一個(gè)元素封恰。
如果 p 的初值為 &a[0],那么 p + i
和 a + i
就是 a[i] 的地址褐啡。
*(p+5)
*(a+5)
a[5]
這三種表示方法等價(jià)诺舔。
可以看出,數(shù)組名后面的括號(hào) [],實(shí)際上是變址運(yùn)算符低飒,指向數(shù)組元素的指針變量也可以帶下標(biāo)许昨,如 p[i]
與 *(p+i)
等價(jià)。
效率比較:
-
下標(biāo)法:a[i]
int a[10]; int i; for(i = 0; i < 10; i++) { cout<<a[i]<<endl; }
-
指針法:*(a + i)
int a[10]; int i; for(i = 0; i < 10; i++) { cout<<*(a + i)<<endl; }
-
用指針變量指向數(shù)組元素
int a[10]; int i; for(p = a; p < (a + 10); p++) { cout<<*p<<endl; }
1 和 2 的執(zhí)行效率相同褥赊,C++ 編譯系統(tǒng)是將 a[i] 轉(zhuǎn)換為 *(a + 1) 處理的糕档,對(duì)每個(gè) a[i] 都分別計(jì)算地址 a + i x d,然后訪問該元素拌喉。3 比 1 和 2 快速那,用指針變量直接指向元素,不必每次都重新計(jì)算地址尿背。
在使用指針變量指向數(shù)組元素是端仰,應(yīng)切實(shí)保證指向數(shù)組中有效的元素。
C++ 編譯系統(tǒng)將形參數(shù)組名一律作為指針變量來處理田藐。
函數(shù)與指針
只須將函數(shù)名 max 賦給 p荔烧,不能寫成 p = max(a,b)
int * a(int x, int y);
a 是函數(shù)名,調(diào)用它以后m能得到一個(gè)指向整型數(shù)據(jù)的指針(地址)汽久。
指針數(shù)組和指向指針的指針
指針數(shù)組
int * p[4]
由于 [] 比 * 優(yōu)先級(jí)高鹤竭,因此 p 先與 [4] 結(jié)合,形成 p[4] 形式景醇,這顯然是數(shù)組形式诺擅。不要寫成 int 這是指向一維數(shù)組的指針變量。
* (name + i ++)
表示先求 * 的值啡直,即 name 它是一個(gè)地址烁涌。將它賦給 p,然后 i 加 1酒觅,最后輸出以 p 地址開始的字符串撮执。
指向指針的指針
由于 name[i] 的值是地址(即指針),因此 name + i 就是指向指針型數(shù)據(jù)的指針舷丹。
// 指針變量(比如變量 a 的地址)
char * p
// 存儲(chǔ) a 的地址的指針的地址
char *(* p)
* p = 'C++'
** p 指向 ‘C++’ 的第一個(gè)字符元素的內(nèi)容
const 指針
用指向常量的指針變量只是限制了通過指針變量改變它指向的對(duì)象的值抒钱。
-
const 類型名 * p (指向常量的指針變量)
p 的指向可變,但 p 指向的對(duì)象的值不可變颜凯。
int a = 12; int b = 15; const int * p = & a; p = &b; //合法谋币,p 的指向可變 * p = 20; //非法,p 指向的對(duì)象的值不可變 a = 15; //合法症概,a 不是 const 常量
如果想絕對(duì)保證 a 的值始終不變蕾额,應(yīng)當(dāng)把 a 定義為常變量。
-
int * const p (常指針變量)
指針變量的指向不可變彼城,但指向變量的值可變
int a = 12; int b = 15; int * const p = & a; p = &b; //非法诅蝶,p 的指向不可變 * p = 20; //合法退个,p 指向變量的值可變
-
const int a
a 的值不可變
const int a = 12; a = 20; //非法
void 指針類型
該空間尚未使用,其中沒有數(shù)據(jù)调炬,談不上指向什么類型的數(shù)據(jù)语盈,故返回一個(gè) void *
類型的指針,表示它不指向確定的具有類型的數(shù)據(jù)缰泡。
指針運(yùn)算
指針變量可以有空值刀荒,即該指針變量不指向任何變量,它可以這樣表示:
// iostream 頭文件中已定義了符號(hào)常量 NULL 代表整數(shù) 0
p = NULL;
如果兩個(gè)指針不指向同一個(gè)數(shù)組棘钞,則比較是無意義的缠借。如果一定要對(duì)不同類型的指針變量賦值,可以用到強(qiáng)制類型轉(zhuǎn)換武翎。
引用
在數(shù)據(jù)類型名后面出現(xiàn)的 & 是引用聲明符號(hào)烈炭,在其他場(chǎng)合出現(xiàn)的都是地址符:
char &d = c; // 引用的聲明符
int * p = & a; //地址符
在聲明一個(gè)引用后,不能再使之作為另一變量的引用宝恶。
int a1, a2;
int &b = a1;
int &b = a2; //非法
引用其實(shí)就是一個(gè)指針常量符隙,它的指向不可改變。
引用作為函數(shù)參數(shù)
傳遞變量的地址:形參是指針變量垫毙,實(shí)參是一個(gè)變量的地址霹疫。調(diào)用函數(shù)時(shí),形參(指針變量)得到實(shí)參變量的地址综芥,因此指向?qū)崊⒆兞繂卧?/p>
實(shí)參不是地址而是整型變量名丽蝎,由于形參是引用,系統(tǒng)會(huì)自動(dòng)將實(shí)參的地址傳遞給形參膀藐,注意:此時(shí)傳送的是實(shí)參變量的地址而不是實(shí)參變量的值屠阻。實(shí)參是地址,傳遞的是地址额各,故仍然是值傳遞国觉。方式(3)中實(shí)參是變量名,而傳遞的是變量的地址虾啦,這才是傳址方式麻诀。
第七章 用戶自定義數(shù)據(jù)類型
引用結(jié)構(gòu)體變量
.
是成員運(yùn)算符,它在所有運(yùn)算符中優(yōu)先級(jí)最高傲醉,因此可以把 student.num
作為一個(gè)整體來看待蝇闭。
指向結(jié)構(gòu)體變量的指針
C 和 C++ 提供了指向結(jié)構(gòu)體變量的運(yùn)算符 ->
,形象的表示“指向”關(guān)系。例如硬毕,p->num
表示指針 p 當(dāng)前指向的結(jié)構(gòu)體變量中的成員 num呻引。
p->n++
得到p指向的結(jié)構(gòu)體變量中的成 員 n的值,用完該值后使它加 1昭殉。
++p->n
得到 p 指向的結(jié)構(gòu)體變量中的成員 n 的值苞七,并使之加 1藐守,然后再使用它挪丢。
用結(jié)構(gòu)體變量和指向結(jié)構(gòu)體變量的指針構(gòu)成鏈表
用結(jié)構(gòu)體變量和指向結(jié)構(gòu)體變量的指針構(gòu)成鏈表蹂风,最有一個(gè)元素不再指向其他元素,它成為“表尾”乾蓬,它的地址部分放到一個(gè)“NULL”(表示“空地址”)惠啄,鏈表到此結(jié)束。
所有節(jié)點(diǎn)(結(jié)構(gòu)體變量)都是在程序中定義的任内,不是臨時(shí)開辟的撵渡,也不能用完后釋放,這種鏈表成為靜態(tài)鏈表死嗦。
動(dòng)態(tài)鏈表則是指?jìng)€(gè)結(jié)點(diǎn)是可以隨時(shí)插入和刪除的趋距,這些節(jié)點(diǎn)并沒有變量名,只能先找到一個(gè)結(jié)點(diǎn)上越除,才能根據(jù)它提供的下一個(gè)結(jié)點(diǎn)的地址找到下一個(gè)結(jié)點(diǎn)节腐。
結(jié)構(gòu)體類型數(shù)據(jù)最為函數(shù)參數(shù)
調(diào)用函數(shù)時(shí)形參要單獨(dú)開辟內(nèi)存單元,如果結(jié)構(gòu)體變量占的存儲(chǔ)空間很大摘盆,則在虛實(shí)結(jié)合時(shí)控件和時(shí)間的開銷都比較大翼雀,效率是不高的。
用 new 和 delete 運(yùn)算符進(jìn)行動(dòng)態(tài)分配和撤銷存儲(chǔ)空間
new 運(yùn)算符使用的一般格式:
new 類型 [初值]
注意:用 new 分配數(shù)組空間時(shí)不能指定初始值
delete 運(yùn)算符使用的一般格式為:
delete 指針變量
或
delete [] 指針變量
在指針變量前面加一對(duì)方括號(hào)孩擂,表示是對(duì)數(shù)組空間的操作狼渊。
枚舉類型
枚舉元素按常量處理,故稱枚舉常量类垦,它們不是常量狈邑,不能對(duì)它們賦值,即枚舉元素的值是固定的蚤认。
第八章 類和對(duì)象的特性
聲明類類型
如果在類的定義中既不指定 private米苹,也不指定 public,則系統(tǒng)就默認(rèn)為是私有的烙懦。
除了 private 和 public之外驱入,還有一種成員訪問限定符 protect(受保護(hù)的),用protect聲明的成員不能被類外訪問(這點(diǎn)與私有成員類似)氯析,但可以被派生類的成員函數(shù)訪問亏较。
成員函數(shù)的性質(zhì)
::
是作用域限定符(field qualifier)或稱作用域運(yùn)算符,用它聲明函數(shù)是屬于哪個(gè)子類的掩缓。
函數(shù)名前既無類名又無作用域運(yùn)算符雪情,表示函數(shù)不屬于任何類,這個(gè)函數(shù)不是成員函數(shù)你辣,而是全局函數(shù)巡通。
內(nèi)置成員函數(shù)
在類體中定義的成員函數(shù)的規(guī)模一般都很小尘执,而系統(tǒng)調(diào)用函數(shù)的過程所花費(fèi)的時(shí)間開銷相對(duì)是比較大的,為減少時(shí)間的開銷宴凉,如果在類體中定義的成員函數(shù)中不包括循環(huán)等控制結(jié)構(gòu)誊锭,C++ 系統(tǒng)就自動(dòng)把它們作為內(nèi)置(inline)函數(shù)來處理。
成員函數(shù)的存儲(chǔ)方式
每個(gè)對(duì)象所占用的存儲(chǔ)空間只是該對(duì)象的數(shù)據(jù)成員所占的存儲(chǔ)空間弥锄,而不包括函數(shù)代碼所占用的存儲(chǔ)空間丧靡。
第九章 怎樣使用類和對(duì)象
對(duì)象的初始化
不能在類生命中對(duì)數(shù)據(jù)成員初始化,因?yàn)轭惒⒉皇且粋€(gè)實(shí)體籽暇,而是一種抽象類型温治,并不占存儲(chǔ)空間,顯然誤觸容納數(shù)據(jù)戒悠。
用構(gòu)造函數(shù)實(shí)現(xiàn)數(shù)據(jù)成員的初始化
在類外定義構(gòu)造成員函數(shù)熬荆,要加上類名和域限定符。
在建立對(duì)象時(shí)系統(tǒng)為該對(duì)象分配存儲(chǔ)單元绸狐,此時(shí)執(zhí)行構(gòu)造函數(shù)卤恳。
構(gòu)造函數(shù)的重載
無參構(gòu)造函數(shù)應(yīng)注意正確書寫定義對(duì)象的語句
請(qǐng)記住:構(gòu)造函數(shù)是不能被用戶顯式調(diào)用的
使用默認(rèn)參數(shù)的構(gòu)造函數(shù)
由于不需要實(shí)參也可以調(diào)用構(gòu)造函數(shù)六孵,因此全部參數(shù)都指定了一個(gè)默認(rèn)值的構(gòu)造函數(shù)也屬于默認(rèn)的構(gòu)造函數(shù)纬黎。
編譯系統(tǒng)無法識(shí)別應(yīng)該調(diào)用那個(gè)構(gòu)造函數(shù),出現(xiàn)歧義性
在一個(gè)類中定義了全部是默認(rèn)參數(shù)的構(gòu)造函數(shù)后劫窒,不能再定義重載構(gòu)造函數(shù)
析構(gòu)函數(shù)
如果用戶沒有定義析構(gòu)函數(shù)本今,C++ 編譯系統(tǒng)會(huì)自動(dòng)生成一個(gè)析構(gòu)函數(shù),但它只是徒有析構(gòu)函數(shù)的名稱和形式主巍,實(shí)際上什么操作都不進(jìn)行冠息。
調(diào)用構(gòu)造函數(shù)和析構(gòu)函數(shù)的順序
先構(gòu)造的后析構(gòu),后構(gòu)造的先析構(gòu)孕索。相當(dāng)于一個(gè)棧逛艰,先進(jìn)后出。
指向?qū)ο蟪蓡T的指針
Time * pt; //定義 pt 是指向 Time 類對(duì)象的指針變量
Time tl; //定義 tl 為 Time 類對(duì)象
pt = & tl; //將 tl 的起始地址賦給 pt
* pt; //pt 所指向的對(duì)象搞旭,即 tl散怖;
//以下表示是等價(jià)的
(* pt).hour;
pt -> hour;
指針變量的類型必須與賦值號(hào)右側(cè)函數(shù)的類型相匹配,要求在以下3方面都要匹配:1.函數(shù)參數(shù)的類型和參數(shù)個(gè)數(shù)肄渗;2镇眷、函數(shù)返回值類型;3.所屬的類
定義指向公用成員函數(shù)的指針變量的一般形式為:
數(shù)據(jù)類型名 (類名 :: * 指針變量名)(參數(shù)列表);
//形如:
void(Time:: *p2)()
使指針變量指向一個(gè)公用成員函數(shù)的一般形式為:
指針變量名 = & 類名 :: 成員函數(shù)名
//形如
p2 = &Time::get_time;
常對(duì)象
常對(duì)象必須有初值翎嫡,在常對(duì)象的生命周期中欠动,對(duì)象中的所有數(shù)據(jù)成員的值都不能被修改
定義常對(duì)象的一般形式為:
類名 const 對(duì)象名[(實(shí)參表)];
也可以把const寫在最左邊:
const 類名 對(duì)象名[(實(shí)參表)];
與上面的格式是等價(jià)的具伍。
在定義常對(duì)象時(shí)翅雏,必須同時(shí)對(duì)之初始化,之后不能再改變人芽。
常對(duì)象成員
-
常成員函數(shù)
//注意const的位置在函數(shù)名和括號(hào)之后 viod get_time() const;
指向?qū)ο蟮某V羔?/h3>
指向?qū)ο蟮某V羔樧兞康闹挡荒芨淖兺福词冀K指向同一個(gè)對(duì)象,但可以改變其所指向的對(duì)象的值啼肩。
往往常指針作為函數(shù)的形參橄妆,目的是不允許在函數(shù)執(zhí)行過程中改變指針變量的值衙伶,使其始終指向原來的對(duì)象祈坠。
指向常對(duì)象的指針變量
一個(gè)對(duì)象已經(jīng)被聲明為常變量,只能用指向常變量的指針變量指向它矢劲。
指向常變量的指針變量除了可以指向常變量赦拘,還可以指向未被聲明為const的變量。此時(shí)不能通過此指針變量來改變?cè)撟兞康闹怠?/p>
指向常對(duì)象的指針最常用于函數(shù)的形參芬沉,目的是在白虎形參指針?biāo)赶虻膶?duì)象躺同,使它在函數(shù)執(zhí)行過程中不被修改。
以下是非法的:
- 形參:指向非 const 型變量的指針;實(shí)參 const 變量的地址;
因?yàn)閰?shù)傳遞本質(zhì)是值傳遞/地址傳遞椒振。過程:形參指向?qū)崊⒎杞痢R驗(yàn)榉?const 型變量指針只能指向非 const 型變量。所以以上是非法的芦疏。
在函數(shù)調(diào)用時(shí)將建立一個(gè)新的對(duì)象,它是實(shí)參對(duì)象的拷貝
對(duì)象的動(dòng)態(tài)建立和釋放
用new運(yùn)算符動(dòng)態(tài)地分配內(nèi)存后,將返回一個(gè)指向新對(duì)象的指針涛救。
對(duì)象的賦值
對(duì)象的賦值只對(duì)其中數(shù)據(jù)成員賦值,而不對(duì)成員函數(shù)賦值业扒。
不同對(duì)象的成員函數(shù)時(shí)同一個(gè)函數(shù)代碼段检吆,不需要,也無法對(duì)它賦值程储。
靜態(tài)成員
靜態(tài)數(shù)據(jù)成員可初始化蹭沛,但只能在類體外進(jìn)行初始化。
公用靜態(tài)數(shù)據(jù)成員與全局變量不同章鲤,靜態(tài)數(shù)據(jù)成員的作用域只限于定義該類的作用域內(nèi)(如果是在一個(gè)函數(shù)中定義類摊灭,那么其中靜態(tài)數(shù)據(jù)成員的作用域就是在此函數(shù)內(nèi))
靜態(tài)數(shù)據(jù)成員函數(shù)
非靜態(tài)成員函數(shù)有 this 指針,而靜態(tài)成員函數(shù)沒有this指針咏窿。由此決定了靜態(tài)成員函數(shù)不能訪問本類中的非靜態(tài)成員斟或。
在 C++ 程序中最好養(yǎng)成這樣的習(xí)慣:只用靜態(tài)成員函數(shù)引用靜態(tài)數(shù)據(jù)成員,而不引用非靜態(tài)數(shù)據(jù)成員集嵌。
友元函數(shù)
在類外定義的且未用類最限定的函數(shù)萝挤,是非成員函數(shù)御毅,不屬于任何類。
友元類
- 友元的關(guān)系是單向的而不是雙向的怜珍。
- 友元的關(guān)系不能傳遞端蛆。
類模板
一般形式為:
類模板名 <實(shí)際類型名> 對(duì)象名(參數(shù)表);
運(yùn)算符重載
重載運(yùn)算符的規(guī)則
重載的運(yùn)算符必須和用戶定義的自定義類型的對(duì)象一起使用,其參數(shù)至少應(yīng)有一個(gè)是類對(duì)象(或類對(duì)象的引用)酥泛,參數(shù)不能全是 C++ 的標(biāo)準(zhǔn)類型
運(yùn)算符重載函數(shù)作為類成員函數(shù)和友元函數(shù)
將雙目運(yùn)算符重載為友元函數(shù)時(shí)今豆,由于友元函數(shù)不是該類的成員函數(shù),因此在函數(shù)的形參表中必須有兩個(gè)參數(shù)柔袁,不能省略呆躲。
用轉(zhuǎn)換構(gòu)造函數(shù)進(jìn)行不同類型數(shù)據(jù)的轉(zhuǎn)換
通常把有一個(gè)參數(shù)的構(gòu)造函數(shù)作類型轉(zhuǎn)換,所以捶索,稱為轉(zhuǎn)換構(gòu)造函數(shù)插掂。
類型轉(zhuǎn)換函數(shù)
類型轉(zhuǎn)換函數(shù)的作用是將一個(gè)類的對(duì)象轉(zhuǎn)換成另一個(gè)類型的數(shù)據(jù)。形式如:
operator 類型名()
{ ... }
在函數(shù)名前不能指定函數(shù)類型腥例,函數(shù)沒有參數(shù)辅甥。類型轉(zhuǎn)換函數(shù)只能作為成員函數(shù),因?yàn)檗D(zhuǎn)換的主體是本類的對(duì)象燎竖,不能作為友元函數(shù)或普通函數(shù)璃弄。
如果運(yùn)算符重載函數(shù)為成員函數(shù),它的第一個(gè)參數(shù)必須是本類的對(duì)象构回。當(dāng)?shù)谝粋€(gè)操作數(shù)不是類對(duì)象時(shí)夏块,不能將運(yùn)算符函數(shù)重載為成員函數(shù),如果將運(yùn)算符“+” 重載為類的成員函數(shù)捐凭,交換律不適用拨扶。
類型轉(zhuǎn)換函數(shù)與運(yùn)算符重載不共存。因?yàn)榭赡艹霈F(xiàn)二義性茁肠。
第十一章 繼承與派生
派生類的聲明方式
基類名前有 public 的稱為公用繼承患民。如果不寫此項(xiàng),默認(rèn)為 privite(私有的)
派生類成員的訪問屬性
基類的成員函數(shù)只能訪問基類的成員垦梆,而不能派生類的成員匹颤。
-
公用繼承
基類的公用成員和保護(hù)成員在派生類中保持原有訪問屬性,私有成員仍為基類私有
-
私有繼承
基類的公有成員和保護(hù)成員在派生類中成了私有成員托猩,私有成員仍為基類私有
-
受保護(hù)繼承
基類的公有成員和保護(hù)成員在派生類中成了保護(hù)成員印蓖,私有成員仍為基類私有
派生類的構(gòu)造函數(shù)和析構(gòu)函數(shù)
基類的構(gòu)造函數(shù)式不能繼承的,對(duì)繼承過來的基類成員初始化的工作也要由派生類的構(gòu)造函數(shù)承擔(dān)京腥。解決這個(gè)問題的思路是:在執(zhí)行派生類的構(gòu)造函數(shù)時(shí)赦肃,調(diào)用基類的構(gòu)造函數(shù)。
簡(jiǎn)單的派生類構(gòu)造函數(shù)
在類中對(duì)派生類構(gòu)造函數(shù)作聲明時(shí),不包括上面給出的一般形式中的基類的構(gòu)造函數(shù)名(參數(shù)表)部分
有子對(duì)象的派生類的構(gòu)造函數(shù)
應(yīng)當(dāng)在建立對(duì)象時(shí)對(duì)它的數(shù)據(jù)成員初始化他宛。
派生類構(gòu)造函數(shù)的任務(wù)應(yīng)該包括:
- 對(duì)基類數(shù)據(jù)成員初始化
- 對(duì)子對(duì)象數(shù)據(jù)成員初始化
- 對(duì)派生類數(shù)據(jù)成員初始化
定義派生類構(gòu)造函數(shù)的一般形式為:
派生類構(gòu)造函數(shù)名(總參數(shù)表):基類構(gòu)造函數(shù)名(參數(shù)表)船侧,子對(duì)象名(參數(shù)表)
{ 派生類中新增數(shù)據(jù)成員初始化語句 }
派生類構(gòu)造函數(shù)的特殊形式
如果在基類中沒有定義構(gòu)造函數(shù),或定義了沒有參數(shù)的構(gòu)造函數(shù)厅各,那么镜撩,在定義派生類構(gòu)造函數(shù)時(shí)可以不寫基類構(gòu)造函數(shù)。因此此時(shí)派生類構(gòu)造函數(shù)沒有向基類構(gòu)造函數(shù)傳遞參數(shù)的任務(wù)队塘。在調(diào)用派生類構(gòu)造函數(shù)時(shí)袁梗,系統(tǒng)會(huì)自動(dòng)首先調(diào)用基類的默認(rèn)構(gòu)造函數(shù)。
派生類的析構(gòu)函數(shù)
在執(zhí)行派生類的析構(gòu)函數(shù)時(shí)憔古,系統(tǒng)會(huì)自動(dòng)調(diào)用基類的析構(gòu)函數(shù)和子對(duì)象的析構(gòu)函數(shù)遮怜。調(diào)用的順序與構(gòu)造函數(shù)相反:先執(zhí)行派生類自己的析構(gòu)函數(shù),然后調(diào)用子對(duì)象的析構(gòu)函數(shù)投放,最后調(diào)用基類的析構(gòu)函數(shù)奈泪。
多重繼承
形式如:
派生類構(gòu)造函數(shù)名(總參數(shù)表):基類 1 構(gòu)造函數(shù)(參數(shù)表),基類 2 構(gòu)造函數(shù)(參數(shù)表), 基類 3 構(gòu)造函數(shù)(參數(shù)表)
{ 派生類中新增數(shù)據(jù)成員初始化語句 }
聲明基類的順序決定了基類構(gòu)造函數(shù)的調(diào)用順序
多重繼承引發(fā)的二義性問題
基類的同名成員在派生類中被屏蔽灸芳。成為不可見的。因此如果在定義派生類對(duì)象的模塊中通過對(duì)象名訪問同名的成員拜姿,則訪問的是派生類的成員烙样。請(qǐng)注意:不同的成員函數(shù),只有在函數(shù)名和參數(shù)個(gè)數(shù)相同蕊肥、類型相匹配的情況下才發(fā)生同名覆蓋谒获。
虛基類
虛基類使得在繼間接共同基類時(shí)只保留一份成員。
需要注意壁却,為了保證虛基類在派生類中只繼承一次批狱,應(yīng)當(dāng)在該基類的所有直接派生類中聲明為虛基類,否則仍然會(huì)出現(xiàn)對(duì)基類的多次繼承展东。
由于虛基類在派生類中只有一份數(shù)據(jù)成員赔硫,所以這份數(shù)據(jù)成員的初始化必須由派生類直接給出。
C++ 編譯系統(tǒng)只執(zhí)行最后的派生類對(duì)虛基類的構(gòu)造函數(shù)的調(diào)用盐肃,而忽略虛基類的其他派生類對(duì)虛基類的構(gòu)造函數(shù)的調(diào)用爪膊,這就保證了虛基類的數(shù)據(jù)成員不會(huì)被多次初始化。
基類與派生類的轉(zhuǎn)換
A al; //定義基類 A 對(duì)象 al
B bl; //B 是 A 的派生類
A& r = al; //定義基類 A 對(duì)象的引用 r砸王,并引用 al 對(duì)其初始化
這時(shí)推盛,r 是 al 的引用(別名),r 和 al 共享同一段存儲(chǔ)單元谦铃。
A& r = bl;
此時(shí) r 并不是 bl 的別名耘成,也不是與 bl 共享同一段存儲(chǔ)單元,它只是 bl 中基類部分的別名,r 與 bl 中基類部分共享同一段存儲(chǔ)單元瘪菌,r 與 bl 具有相同的其實(shí)地址件豌。
即基類的引用類型,指向了派生類的變量控嗜。指向的也是派生類中從基類繼承的部分茧彤。
繼承與組合
在一個(gè)類中以另一個(gè)類的對(duì)象作為數(shù)據(jù)成員的,稱為類的組合疆栏。
第十二章 多態(tài)性與虛函數(shù)
派生類對(duì)象可以替代基類對(duì)象向基類對(duì)象的引用初始化或賦值曾掂。調(diào)用的不是在 Circle 中聲明的運(yùn)算符重載函數(shù),而是在 Point 中聲明的運(yùn)算符重載函數(shù)壁顶,輸出的是“點(diǎn)”的信息珠洗,而不是“圓”的信息。
這兩個(gè) area 函數(shù)不是重載函數(shù)若专,它們不僅函數(shù)名相同许蓖,而且函數(shù)類型和參數(shù)個(gè)數(shù)都相同,兩個(gè)同名函數(shù)不在同一個(gè)類中调衰,而是分別在基類和派生類中膊爪,屬于同名覆蓋。
虛函數(shù)的作用
編譯系統(tǒng)按照同名覆蓋的原則決定調(diào)用的對(duì)象嚎莉。
C++ 的虛函數(shù)就是用來解決動(dòng)態(tài)多態(tài)的問題的米酬。所謂虛函數(shù),就是在基類聲明函數(shù)是虛擬的趋箩,并不是實(shí)際存在的函數(shù)赃额,然后在派生類中才正式定義此函數(shù)。
本來叫确,基類指針是用來指向基類對(duì)象的跳芳,如果用它指向派生類對(duì)象,則自動(dòng)進(jìn)行指針類型轉(zhuǎn)換竹勉,將派生類的對(duì)象的指針先轉(zhuǎn)換為基類的指針飞盆,這樣,基類指針指向的是派生類中的基類部分饶米。
有時(shí)在基類中定義的非虛函數(shù)會(huì)在派生類中被重新定義桨啃,如果用基類指針調(diào)用該成員函數(shù),則系統(tǒng)會(huì)調(diào)用對(duì)象中基類部分的成員函數(shù)檬输;如果用派生類指針調(diào)用該函數(shù)照瘾,則系統(tǒng)會(huì)調(diào)用派生類對(duì)象中的成員函數(shù),這并不是多態(tài)性行為(使用的是不同類型的指針)
靜態(tài)關(guān)聯(lián)和動(dòng)態(tài)關(guān)聯(lián)
確定調(diào)用的具體對(duì)象的過程稱為關(guān)聯(lián)丧慈。
函數(shù)重載和通過對(duì)象名調(diào)用的虛函數(shù)析命,在編譯時(shí)即可確定其調(diào)用的虛函數(shù)屬于哪一個(gè)類主卫,其過程稱為靜態(tài)關(guān)聯(lián)。
由于是在運(yùn)行階段把虛函數(shù)和類對(duì)象“綁定”在一起的鹃愤,因此稱為動(dòng)態(tài)關(guān)聯(lián)簇搅。
在什么情況下應(yīng)當(dāng)聲明虛函數(shù)
一個(gè)成員函數(shù)被聲明為虛函數(shù)后,在同一類族中的類就不能定義一個(gè)非 virtual 的但與該虛函數(shù)具有相同的參數(shù)软吐。
虛析構(gòu)函數(shù)
先調(diào)用了派生類的析構(gòu)函數(shù)瘩将,再調(diào)用了基類的析構(gòu)函數(shù)。當(dāng)基類的析構(gòu)函數(shù)為虛函數(shù)凹耙,無論指針指的是同一類族中的哪一個(gè)類對(duì)象姿现。
如果將基類的析構(gòu)函數(shù)聲明為虛函數(shù)時(shí),由該函數(shù)所派生的所有派生類的析構(gòu)函數(shù)有都自動(dòng)成為虛函數(shù)肖抱,即使派生類的析構(gòu)函數(shù)與基類的析構(gòu)函數(shù)名字不相同备典。
純虛函數(shù)與抽象類
virtual 函數(shù)類型 函數(shù)名(參數(shù)類別) = 0;
純虛函數(shù)只有函數(shù)的名字而不具備函數(shù)的功能,不能被調(diào)用意述。它只是通知編譯系統(tǒng):在這里聲明一個(gè)虛函數(shù)提佣,待派生類中定義。
抽象類
凡是包含純虛函數(shù)的類的都是抽象類荤崇。因?yàn)榧兲摵瘮?shù)是不能被調(diào)用的拌屏,包含純虛函數(shù)的類是無法建立對(duì)象的。抽象類的作用是作為一個(gè)類族的共同基類天试。
抽象基類不能也不必要定義對(duì)象槐壳。
區(qū)別靜態(tài)關(guān)聯(lián)和動(dòng)態(tài)關(guān)聯(lián)
在編譯階段就能確定調(diào)用的是哪一個(gè)類的虛函數(shù),所以屬于靜態(tài)關(guān)聯(lián)喜每。如果是通過基類指針調(diào)用虛函數(shù),在編譯階段無法從語句本身確定調(diào)用哪一個(gè)類的虛函數(shù)雳攘,只有在運(yùn)行時(shí)带兜,指針指向某一類對(duì)象后,才能確定調(diào)用的是哪一個(gè)類的虛函數(shù)吨灭,故為動(dòng)態(tài)關(guān)聯(lián)刚照。
第十三章 輸入輸出流
istream 類的其他成員函數(shù)
如果到達(dá)文件末尾(遇到文件結(jié)束符),eof 函數(shù)值為非零值(表示真)喧兄,否則為 0(假)无畔。