C++等级考试知识点总结
第一章 C++語言概述
C++是一種面向對象的程序設計語言
- 抽象數據類型
- 封裝和信息隱藏
- 以繼承和派生方式實現程序的重用
- 以運算符重載和虛函數來實現多態性
- 以模板來實現類型的參數化
C++是C語言的超集
- C++繼承了C語言簡明、高效、靈活等眾多優點
- 以前使用C語言編寫的大批軟件可以不加任何修改,直接在C++開發環境下維護
- C語言程序員只需要學習C++擴充的新特性,就可以很快地使用C++編寫程序
面向對象程序設計的三個主要特征
- 封裝性
- 繼承性
- 多態性
C++語言的基本符號
- 字母:包括大字母和小寫字母共52個符號
- 數字:包括0-9共10個字符
- 特殊符號:包括+ - * / = , . _ : ; ? \ “ ‘ ~ | ! # % & () [] {} ^ <> 和空格共30個符號。
C++語言的詞匯
- 關鍵字:也稱保留字,它是由C++語言本身預先定義好的一類單詞。其中是ANSI C標準規定的32個關鍵字,ANSI C++標準補充的29個關鍵字。
- 標識符:是用戶為程序中各種需要命名的“元素”所起的名字。這些元素包括:變量、符號、常量、函數、函數的參數、結構、類、對象等。
- 標識符的命名規則
- 標識符以一個字母或下劃線開頭的,由字母、數字、下劃線組成的字符串
- 不能與任意一個關鍵字同名
- 標識符中的字母區分大小寫
- 標識符不宜過長
- 字面常量
- 運算符
- 標點符號
C++程序的基本框架
一個簡單的C++程序
1
2
3
4
5
6
#include <iostream>
int main()
{
std::cout<<"This a simple C++ program.\n";
return 0;
}
cout是C++中的標準輸出流對象,它通常代表計算機屏幕。
cout在標準頭文件iostream中被聲明(注:標識符cout位于std名字空間中,須用前綴std::進行修飾)。
“<<”是輸出操作符,功能是將它右邊的內容輸出到它左邊的指定設備上。
此程序的運行結果是在屏幕上顯示:This a simple C++ program.
- 注釋:
- //
- /* */
C++程序的開發過程
- 編輯
- 編譯
- 連接
- 運行和調試
第二章 數據類型、運算符和表達式
C++語言的數據類型
基本類型
邏輯性:用關鍵字bool表示,因此又稱為bool型(布爾型)。邏輯型的取值只包括true和false,它們都是C++關鍵字。其中,true對應整數1,false對應整數0,表示邏輯假。
字符型:字符型用關鍵字char表示,因此又稱為char型。字符型的取值范圍是全部基本字符以及ASCII碼集或擴充ASCII碼集對應的全部符號。字符型數據占用1字節(Byte),即8位(bit)空間。
整型:整型用關鍵字int表示。16位計算機中,整型變量占2個字節,而在32位計算機中,整型變量占4個字節。
浮點型:浮點型包括單精度和雙精度,單精度用關鍵字float表示,雙精度用關鍵字float表示。float型數據一般占用4字節(Byte),即32位(bit)空間;double型數據一般占用8字節,即64位空間。
空值型:空值型用關鍵字void表示,空值型的取值為空。
基本類型的派生類型
派生類型聲明符由基本類型關鍵字char、int、float、double前面加上類型修飾符組成。類型修飾符包括:
- short 短類型,縮短字長
- long 長類型,家常字長
- signed 有符號類型,取值范圍包括正負值
- unsigned 無符號類型,取值范圍包括正值
常量
常量是指在程序執行過程中值不改變的量。常量有兩個表示形式,即字面常量和符合常量。字面常量的類型是根據書寫形式來區分的,例如:15,-0.226,’a’,”Hello Word”等都是字面常量,他們的類型分別是:整型、浮點型、字符型、字符串型,每個字面常量的字面本身就是它的值。符號常量是一個標識符,在程序中必須遵循“先聲明,后使用”的原則。
邏輯常量:值是true或false。
字符常量:簡稱字符,以單引號作為起止符號,中間有一個或若干個字符。例如,’a’和’&’,單引號中間有一個字符,這是一般意義上的字符常量;除此之外還有一種特殊形式的字符常量,例如:’\n’,’\146’,’\x6E’等以“\”開頭的包括多個字符的字符序列也都是符合規定的字符常量。
整型常量:十進制整數、八進制整數和十六進制整數。
實型常量:
定點表示
定點表示的實數簡稱定點數,即以小數形式表示實數。
定點表示的實數由一個正好或負號(正號可以省略)后接若干個十進制數字和一個小數點組成,這個小數點可以處在任何一個數字位的前面或后面。
浮點表示
浮點標書的實數簡稱浮點數,即以指數形式表示實數。
對于一個浮點數,若將它尾數中的小數點調整到最左邊第一個非零數字的后面,則稱它為規格化(或標準化)浮點數,這有些類似于數學中的科學計數法。例如41.6E8和-0.077E5是非規格化的。
實型常量分為:單精度(float)、雙精度(double)和長雙精度(long double)。
枚舉常量:是枚舉類型中定義的值,即枚舉值。
枚舉類型的語法格式為:
enum <類型名>{ <枚舉值表> }
變量
變量是程序中用于存儲信息的單元,它對應于某個內存空間。
變量的定義:
變量聲明語句的一般格式:
[<存儲類>] <類型名> <變量名>[=<初值表達式>]存儲類:有四種,分別是auto、register、static、extern,默認的存儲類是auto。
類型名:已存在的一種數據類型名稱,如char、short、int、long、float、double等基本數據類型名,或者用戶定義的數據類型名。
變量名:用戶定義的一個標識符,用來表示一個變量,該變量可以可以通過后面的可以選項賦予一個值,成為給變量賦初值。若變量名后不帶有初始表達式,則不為變量賦予任何值,此時的變量值不確定。
初值表達式:是一個表達式,它的值就是賦予變量的初值。
變量的使用方式
全局變量和局部變量
全局變量:在所有函數定義、類定義和程序塊之外聲明的變量
局部變量:在某個函數定義、類定義或程序塊之內聲明的變量
生存期與作用域
變量的存儲類屬性
auto變量:用關鍵字auto聲明的局部變量稱為自動變量。auto為變量聲明時的默認存儲類別,即在變量定義時,如果不顯示標明存儲類別,則系統自動按auto變量處理。auto變量所占用存儲空間的分配和釋放工作有系統自動完成。
register變量:用關鍵字register聲明的局部變量稱為寄存器變量。register變量可能以寄存器作為其存儲空間。
static變量:用關鍵字static聲明的變量稱為靜態變量。
extern變量:用關鍵字extern聲明的變量稱為外部變量。
typedef類型說明
- 使用關鍵字typedef可以為已有類型名定義一個新類型名。
- 語法格式
typedef<已有類型名> <新類型名>
符號變量聲明語句
符號常量在使用之前必須先進行定義。符號常量定義語句同變量定義語句類似,其語法格式為:
const <類型名> <符號常量名> = <初值表達式>,…;
運算符和表達式
運算符和表達式概念
- C++語言中運算符可以根據其運算分量個數的多少分為單目(或一元)運算符 、 雙目(或二元)運算符 、 三目(或三元)運算符3類。
運算類型與運算符
每一種運算與其他運算的區別在于以下3個方面:
- 參與運算的運算分量的數量和類型
- 運算結果的數據類型
- 運算的具體操作
同一類運算可以組成一種運算類型,凡是具有相同運算分量和結果類型的運算劃分為同一類運算,比如:算術運算符、關系運算符、邏輯運算、位運算等。
賦值運算
賦值運算是一種雙目運算,其形式為:
<變量名> = <表達式>
賦值運算的具體操作作為:先計算右端表達式的值,然后把該值賦給左端變量
算術運算符和算術表達式
算術運算是指int型、float型、double型(也包括char型)的數值類數據計算后,得到同一類型數據的運算。算術運算中所使用的運算符稱為算術運算符。
單目算術運算符包括:-(單減)、++(增量)和 –(減量)
單減運算的格式為:-<運算分量>
增量運算分為前綴和后綴增量
雙目算術運算符包括:+、-、*、/、%(取余)。
算術表達式:由算術運算符(包括單目和雙目)連接運算分量而組成的式子稱為算術表達式。
關系運算符和關系表達式
C++語言提供了6種關系運算符,它們是:
- < 小于
- <= 大于等于
- 大于
-
= 大于等于
- == 等于
- != 不等于
關系運算的使用格式
- <運算分量> <關系運算符> <運算分量>
邏輯運算符合邏輯表達式
C++語言提供了3種邏輯運算符,它們是:
- ! 邏輯非
- && 邏輯與
- || 邏輯或
邏輯運算符的使用格式為:
- <邏輯運算符! ><運算分量>
- <運算分量> <邏輯運算符&&或||> <運算分量>
位運算
- C++提供6種運算符:
- 雙目位運算符:&(按位與)、|(按位或)、^(按位異或)、>>(按位右移)、<<(按位左移)
- 單目位運算符:~(按位取反)
其他運算
條件運算符
使用格式:
<表達式1>?<表達式2>:<表達式3>
逗號運算符
- C++中使用逗號運算符指明對多個表達式進行順序求值
使用格式:
<表達式1>,<表達式2>,...,<表達式3>
sizeof
- 使用運算符sizeof可以進行字長提取操作,因此sizeof運算符又稱為字長提取符
使用格式:
sizeof(<運算分量>)字長提取運算的結果為一個整數,該整數表示指定的類型或變量的字節長度,即在內存中占用的字節(Byte)數。
圓括號運算符
- C++中不僅將圓括號()歸為運算符,而且根據不同的使用方式,可以對圓括號運算符的功能作出以下3種不同的解釋。
(1)圓括號用于函數調用,格式是:
<函數名>(<實參表>)(2)圓括號用于強制類型轉換,格式是:
(<類型名>)<表達式>(3)圓括號用于類型構造,格式是:
<類型名>(<表達式>)
優先級和結合性
C++中運算符的種類相當豐富,每個運算符的使用方法和操作方式也各不相同。
根據運算符的優先級和結合性,可以將表達式的計算順序規則總結為一下3條:
有限計算帶有括號的子表達式。
在沒有括號的部分,依照運算符優先級,有高到低進行計算。
具有相同優先級的運算符,按照結核性規定,依次進行計算。
運算符優先級:“==”高于“=”
第三章 基本控制結構
C++語句
- 語句是C++程序中的基本功能單位。
- C++語句按照不同功能大體分為6種類型:
- 聲明語句
- 表達式語句
- 選擇語句
- 循環語句
- 跳轉語句
- 復活語句
順序結構
在一個沒有選擇和循環結構的程序中,語句將按照書寫的先后順序,從左到右,自上而下依次執行。
聲明語句
變量聲明
char ch; //聲明和定義char型變量
int count = 1; //聲明、定義和初始化int型變量
extern int error_num; //聲明int型變量
常量聲明
const int MAX_LEN = 128; //聲明、定義和初始化int型常量
函數聲明
double sqrt(double);
類型聲明
typedef unsigned int ID; //聲明和定義類型
enmu Color{RED,GREEN,BLUE}; //聲明和定義枚舉
struct Date{int y,m,d}; //聲明和定義結構
class Employee; //聲明類
表達式語句
- C++所有對數據的操作和處理工作都是通過表達式語句來完成的。
基本輸入輸出
- cout<<Expr; //數據輸出操作
- cin>>Var; //數據輸入操作
復合語句與空語句
- 復合語句和空語句并不是功能上獨立的一類語句。但是,復合語句能夠實現語句塊的概念
- 空語句也可以在一些情況下排上用場
有了復合語句和空語句會使C++程序的設計變得更加方便
選擇結構
if語句
- 基本的if語句
- if…else語句
if語句的嵌套
注意:C++中規定,else關鍵字總是與它前面最近的未匹配的且課件的那個if關鍵字配對。
switch語句
循環結構
- for語句
- while語句
- do…while語句
- 循環的嵌套
跳轉語句
break:只用于循環和switch語句中
continue:只用于循環語句。功能:跳轉本次循環,繼續下一輪循環。
return:只在函數體中。
goto:跳轉到標記的語句位置。
第四章 數組、指針與引用
- 數組(Array)是由固定數目元素組成的數據結構,同意數組的所有元素的類型都相同。數組元素是通過下標進行訪問的,數組可以是一維的,也可以是多為的,許多重要應用的數據節后都是基于數組的。
數組
一維數組
一維數組的定義
<數據類型><數組名>[<數組長度>]一維數組的初始化
int v1[] = {1,2,3,4}; char v2[] = {'a','b','c','d'};訪問數組
<數組名>[<表達式>]
多維數組
二維數組的定義
<數據類型><數組名>[<表達式1>][<表達式2>]二維數組的初始化
int v1[3][4] = {{1,2,3,4},{1,2,3,4},{1,2,3,4}};訪問數組
<數組名>[<表達式1>][<表達式2>]- 多維數組
字符數組
string類型
string name = "William Jacob";在使用string數據類型之前,需要在程序中包含文件string(# include <string>)并聲明其所在的名字空間std。
在C++字符串由零個或多個字符組成,并且所有字符都由雙引號括住。
字符數組
- 所有的元素都是char類型的數組成為字符數組。
- C++中,空字符用‘\0’來表示。
- 在C++中,空字符(’\0’)用來作為一個字符串結束的標志。
字符數組與字符串之間存在細微的差別,字符串以空字符結尾,即字符串的最后一個字符總是空字符,而字符數組可以不含空字符。
- 常用字符串函數
- C++提供了一系列字符串操作的函數,這些函數都包含在頭文件cstring中,引用:# include <cstring>。
指針
指針(即指針變量)是C++語言最強大的功能之一,同時也是最棘手的功能之一。一個指針是一個特定類型數據的存儲地址。
指針的聲明形式:
<數據類型> * <變量名>- 指針使用兩種特殊的運算符—— * 和 &
- & :一元運算符,用于返回其操作對象的內存地址,其操作對象通常為一個變量。
C++的引用。&:只能在定義時被賦值,&b=a:表明b與a等價
- * :與&的作用相反,用于返回其操作數所指對象的值,因此該運算符要求其操作對象為一個指針。
注意:在使用任何指針變量之前必須先給它賦一個指向合法具體對象的地址值。否則系統會給指針變量賦值一個隨機值,該賦值可能會破壞內存中某個地址空間中的內容,嚴重時將導致程序掛起或機器死機。
- 使一個指針指向一個具體對象的方法有:
- 使用new運算符(或malloc和alloc等函數)給指針分配一個具體空間。
- 將另一個同類型的指針賦給它以獲得值。
- 通過&運算符指向某個對象。
- & :一元運算符,用于返回其操作對象的內存地址,其操作對象通常為一個變量。
- 指針運算
- 指針和整型量可以進行加減
- 若p1和p2為指針,當p1和p2指向同一個類型時,可以進行賦值。如p1=p2,則p1和p2指向同一個對象。
- 兩個指向同一類型的指針,可進行==、>、<等關系運算,其實就是地址的比較。
- 兩個指向同一數組成員的指針可進行相減,結果為兩個指針之間相差元素的個數。
注意兩個指針不能相加
- 幾組常見的指針運算表達式比較
- p++與p+1的區別
- 指針p++結果為p指向下一個元素
- p+1結果為下一個元素的指針,但是p本身不變
- y=*px+1和y=*(px+1)的區別
- *px+1結果取px所指對象內容加1
- *(px+1)結果為px指針加1。
- y=*(px)++和y=*px+1的區別
- *(px)++指先取指針px所指對象內容進行運算,然后對指針px所指對象內容加1
- *px+1 指先取指針px所指對象內容進行運算,然后對指針px加1
指針和數組
- 在C++中,數組的名字就是指向改數組第一個元素(下標為0)的指針,即該數組第一個元素的地址,也即數組的首地址。
一般情況下,一個數組元素的下標訪問a[i]等價于相應的指針訪問*(a+i)
但特別注意的是:數組名和指針(變量)是有區別的,前者是常量,即數組名是一個常量指針,而后者是指針變量。因此盡管可以寫成px=a,但不能寫成a=px,或a++,或px=&a,因為我們不能改變常量的值,也不能取常量的地址。
數組名可作為參數進行傳遞。
- 使用指針的原因
- 指針運算比數組運算的速度快
- 使用指針的另外一個原因是在大量數據傳遞是,傳遞指針要遠比傳遞數據本身效率高的多,如在函數參數傳遞及函數返回值時。
當然,使用指針會給程序帶來安全隱患(如指針懸掛問題),同時降低程序的可讀性。
引用
引用是個別名,建立時必須用另一個數據對象(如一個變量)的名字進行初始化,以指定該引用所代表的數據對象。此后,對引用的任何操作實際上就是對所代表的數據對象的操作。系統不會為引用再次分配存儲空間。
注意:引用運算符與地址操作符使用的是相同的符號(即運算符加載),但它們的韓不一樣,引用運算符只在聲明變量的時候使用,它放在類型名后面。
使用引用時應遵循一定的規則
創建引用時,必須立即對其進行初始化(指針則可以在任何時候被初始化)
一旦一個引用被初始化為一個對象的引用,它就不能再被改變為對另一個對象的引用(指針則可以在任何時候改變為指向另一個對象)
不可能有NULL引用,必須確保引用是對具體合法的對象的引用(即引用應和一塊合法的存儲空間共聯)
用引用傳遞函數參數
如果有占用空間大的對象需要作為函數參數傳遞的時候,在C語言中的做法往往是使用指針,因為這樣可以避免將整個實參對象數據全部復制給形式參數,可以提高程序執行效率。而在C++中,由于引入了引用的該男,因此既可以使用指針,亦可以用引用來做同樣的事情。
引用真作為參數的最大的好處是既可以想指針那樣工作,其實用方式又和一般變量相同。也就是說,引用比指針具有更好的可讀性。
動態存儲分配
靜態存儲分配:到目前為止,程序中用于存儲數據的變量和數組等實體在使用前都必須通過聲明語句進行定義。C++編譯器根據這些聲明語句了解它們所需存儲空間大小,并預先為其分配適當的內存空間。也就是說,這些變量或數組在內存中所占據的空間大小必須在編譯時確定下來,這種內存分配方式成為“靜態存儲分配”。
data++,表示取值 data和data++動態存儲分配:很多情況下,程序中所需要的內存數量只有等到運行時刻才能確定下來,這是就應使用“動態存儲分配”的方式申請獲得指定大小的內存空間,當動態分配的內存閑置不用時同樣有必要對其進行釋放。
- new分配空間
- 對某種類型變量進行動態分配:<指針> = new <類型>
- 對數組進行動態分配:<指針> = new <類型> [<元素個數>]
使用new動態分配的數組與一般定義語句聲明的數組之間的最大區別是,前者的元素個數可以是一個變量,而后者的元素個數必須是常量。
- delete釋放空間
- 單個變量 = delete <指針>
- 數組 = delete[] <指針> (無參數)
- new分配空間
第五章 函數
函數是一個可以獨立完成某個功能的語句塊。C++程序其實就是由一系列的函數組成,main函數是其中的一個函數,C++程序從main函數開始執行。
函數作用:
- 將復雜程序拆成若干易于實現的子程序。
- 將程序中重復出現的功能封裝到一個函數中,這樣,該功能只需在一個函數中實現,在程序中用到該功能的地方只需要調用該函數即可,這樣既提高了程序的開發效率,也提高了程序的可靠性 ,同時也極大地增強了程序的可讀性。
函數的定義
用戶自定義函數形式:
1
2
3
4
<返回類型> <函數名>(<形參列表>)
{
<函數體>
}
- C++中,return是一個關鍵字,當函數執行到return語句時,函數將立即終止執行,并將程序的控制權返回給調用函數。因此,如果執行到main函數中的return語句時,整個程序將終止。
- 當一個函數帶有返回值時,應保證函數每個可能執行路徑上應有返回值。
- return語句的第二種形式用于無返回值的函數,即函數返回類型為void。此時函數進將程序控制返回給調用函數,并不返回一個值。當函數沒有return語句時,在執行完最后一條語句后將返回到調用函數。
函數調用
調用的一般形式:
1 <函數名>(<實參表>) 函數的調用方法分為:
語句調用:通常是不帶返回值的函數。
表達式調用:將被調用的函數作為表達式的一部分進行調用,適用于被調用函數帶有返回值的情況。
參數調用:被調用函數作為另個一函數的一個參數進行調用。
函數原型
在C++中,函數使用之前要預先聲明,這種聲明在標準C++中稱為函數原型。
函數原型的語法:
1 <返回類型> <函數名>(<形參列表>); 函數原型聲明的兩種形式
直接使用函數定義的頭部,并在后面加上一個分號。
在函數原型聲明中省略參數列表中的形參變量名,僅給出函數名、函數類型、參數個數及次序。如int max (int int);
C++中,調用任何函數之前,必須保證它已有原型聲明。函數原型通常放在程序文件的頭部,以使得該文件中所有函數都能調用它們。實際上,標準函數的原型聲明放在了相應的頭文件中。
函數返回類型
根據函數是否帶有參數以及函數是否有返回值,可以將函數分為如下四類:
帶參數的有返回值的函數
不帶參數的有返回值函數
帶參數的無返回值函數
不帶參數的無返回值函數
函數參數
參數的傳遞方式
傳值:將實參的副本傳遞(拷貝)給被調用函數的形參,不改變原值。
傳地址:改變原值
有時需要函數調用來改變實參變量的值,或通過函數調用返回多個值,這時僅靠傳值方式是不能達到目的的。
傳指針屬于顯式傳遞地址,因此盡管傳遞指針可以達到目的,但傳遞方式略顯笨拙,而且也不直觀。
函數引用參數僅在函數定義時說明,而帶引用參數的函數的調用形式與值參數相同。
C++中,當函數參數需要傳遞地址時,建議使用引用來替代指針,因為引用比指針更加直觀。
- 引用的適用情形:
- 要從函數中返回多個值
- 通過函數調用要改動實參值
- 傳遞地址可以潔身拷貝大量數據所需的內存空間和時間
默認參數
C++中,可以為形參指定默認值,在函數調用時沒有指定與形參相對應的實參時就自動使用默認值。默認參數可以簡化復雜函數的調用。
如果一個函數中有多個參數,則默認參數應從右至左逐個定義。
C++引入默認參數使得程序員能夠處理更為復雜的問題。使用默認參數,程序員只需記住針對確切情形有意義的參數,不需要指定常見情況下使用的參數。
函數重載
在C中,編寫函數時必須確保函數名唯一。但是C++中可以共用相同的函數名。
函數重載:用同一個函數名字在不同類型上做相類似的操作就會方便很多,這種情況較函數重載。
C++根據所傳遞的實參的不同,調用相應的函數u,得到期望的效果。
C++中的函數重載中,如果函數知識函數類型不同,而其他(參數個數及類型)完全相同,則不能作為重載函數來使用。
注意:讓重載函數執行不同的功能是非常不好的程序設計風格,同名函數應該具有相同的功能。
內聯函數
- C++引入內聯函數的原因是用它來取代C中的預處理宏函數
內聯函數與宏函數的區別:
- 宏函數是有預處理器對宏進行替換
- 內聯函數是通過編譯器實現的
內聯函數是真正的函數,只有在調用的時候,內聯函數像宏函數一樣展開,所以它沒有一般函數的參數壓棧和退棧操作,減少了調用開銷,因此內聯函數比普通函數執行效率更高。
C++中,使用inline關鍵字來定義內聯函數,inline關鍵字放在函數定義(聲明)中函數類型之前。
編譯器會將在類的說明部分定義的任何函數都認定為內聯函數,即使它們沒有用inline說明。
注意
內聯函數使用方式和一般函數一樣,只不過在程序執行時并不產生實際函數調用,而是在函數調用處將函數代碼展開執行。
內聯函數有一定的局限性,就是函數中的執行代碼不能太多,結構也不能太復雜。如果內聯函數的函數體過大,編譯器將會放棄內聯方式,而是采用普通的方式調用函數。
遞歸函數
如果一個函數在其函數體內,直接或者間接地調用了自己,該函數就被稱為遞歸函數。遞歸是解決某些復雜問題的十分有效的方法。
遞歸適用的場合
數據的定義形式按遞歸定義。
數據之間的關系(即數據結構)按遞歸定義的,如樹的遍歷,圖的搜索等。
問題解決按遞歸算法實現的,例如回溯法。
使用遞歸需要注意以下幾點
用遞歸編寫代碼往往較為簡潔,但要犧牲一定的效率,因為系統處理遞歸函數時都是通過壓棧/退棧的方式實現的。
無論哪種遞歸調用,都必須有遞歸出口,即結束遞歸調用的條件。
編寫遞歸函數時需要進行遞歸分析,既要保證正確使用了遞歸語句,還要保證完成了相應的操作。
變量的生存周期
全局變量:變量由編譯程序在編譯時給其分配存儲空間(稱為靜態存儲分配),并在程序執行過程中始終存在。這類變量的生存周期與程序的運行周期相同。
局部變量:變量由程序運行時自動給其分配存儲空間(稱為動態存儲分配),這類變量為函數(或塊)中定義的自動變量。這類變量的生存周期與函數(或塊)的執行周期相同。
由于作用域的屏蔽效應,如果函數中有同名變量,則不能訪問外部變量。為了能在函數內部訪問外定義的變量,可以使用C++中的作用域運算符::。
當程序較大時,利用名字評比機制是非常必要的,但是這也會導致程序的可讀性變差,好的程序設計風格應盡量避免名字屏蔽。
第六章 類和對象
類是面向對象程序設計的核心,通過抽象數據類型方法實現的一種用戶自定義數據類型,它包含了數據和對數據進行操作的函數,利用類可以實現數據的封裝和隱藏。
類的定義
- 類是一種由用戶定義的復雜數據類型,它是將不同類型的數據和與這些數據相關的操作封裝在一起的集合體。C++中類概念的目標就是為程序員提供一種建立新類型的工具,使這些新類型的使用能夠像內部數據類型一樣方便。
類定義的一般格式:
1
2
3
4
5
6
7
8
9
10
11
12// 類的說明部分
class <類名>
{
public:
<成員函數或數據成員的說明> \ //公有成員,外部接口
protected:
<數據成員或成員函數的說明> \ //保護成員
private:
<數據成員或成員函數的說明> \ //私有成員
};
// 類的實現部分
// <各個成員函數的實現>花括號表示類的聲明范圍,其后的分號表示類申明結束。
類的成員包括數據成員和成員函數,分別描述類所表達的問題的屬性和行為。
關鍵字public、private和protected成為訪問權限修飾符,它們限制了類成員的訪問控制范圍。
各個成員函數的實現既可以在類體內定義,也可以在類體外定義。
如果一個成員函數在類體內進行了定義,它將不出現類的實現部分;如果所有的成員函數都在類體內進行了定義,則可以省略類的實現部分。在類體內定義的成員函數都是內聯函數。
類成員的訪問控制
- 類中的成員具有不同的訪問權限修飾符。這些不同的訪問權限修飾符限制了類成員的不同訪問控制范圍。
三種訪問控制權限:
公有(public):定義類的外部接口,任何來自類外部的訪問都必須通過外部接口進行。
私有(private):私有類型的成員只允許本類的成員函數訪問,來自類外部的訪問都是非法的。
保護(protected):介于共有類型和又有類型之間,在繼承 和派生時可以體現其特點。
類中成員默認的訪問權限是私有的(private)。
類的數據成員
- 類中的數據成員描述類所表達的問題的屬性。數據成員在類體中進行定義,其定義方式與一般變量相同,但對數據成員的訪問要收到訪問權限修飾符的控制。
定義了類的數據成員時,注意的問題:
類中的數據成員可以是任意類型,包括整型、浮點型、字符型、數組、指針和引用等,也可以是對象。
但是要注意的是,只有其他類的對象,才可以作為該類的成員,即作為該類的成員對象而存在。自身類的對象是不可以作為自身類的成員存在的,但自身類的指針可以。
在類體中不允許對所定義的數據成員進行初始化。
類的成員函數
類的成員函數描述類所表達的問題的行為。類中所有的成員函數都必須在類體內進行說明。但成員函數的定義既可以在類體中給出,也可以在類體外給出。
在類外部對成員函數進行定義,一般格式:
1
2
3
4<返回類型> <類名>::<成員函數名>(<參數表>)
{
<函數體>
}成員函數的兩種定義方式的差別:
- 如果一個成員函數的聲明和定義都在類體內,這個成員函數就是內聯函數。
- 如果一個成員函數的聲明在類體內,而定義在類外,這時對該成員函數的調用時按一般函數進行的。
若要將定義在類體外的成員函數也作為內聯函數處理,就必須在成員函數的定義前加上關鍵字inline,以此顯式地說明該成員函數也是一個內聯函數。
成員函數除了可以定義為內聯函數意外,也可以進行重載,可以對其形參設置默認值。
對象的定義
對象是類的實例,一個對象必須屬于一個已知的類。因此定義對象之前,必須先定義該對象所屬的類。
對象的定義格式如下:
1 <類名> <對象名>(<參數表>); <類名>:待定義的對象所述的類的名字。
<對象名>:可以是一個或多個對象名,多個對象名之間用逗號隔開。
<參數表>:初始化對象時需要的,建立對象時可以根據給定的參數調用相應的構造函數對對象進行初始化。無參數時表示調用類的默認構造函數。
除了定義一般對象外,還可以定義對象數組、指向對象的指針或引用。
對象的成員
一個對象的成員就是該對象的類所定義的成員,包括數據成員 和 成員函數。定義對象后,可以使用“.”運算符和“->”運算符訪問對象的成員。
“.”運算符,適用于一般對象和引用對象。
“->”運算符,適用與指針對象(即指向對象的指針)。
實際上,一般對象成員與指針對象成員的表示方法只是形式上有所不同,本質上是相同的。
構造函數和析構函數
構造函數與析構函數的定義
構造函數的作用:在對象被創建時利用特定的值構造對象,將對象初始化為一種特定的狀態(對數據成員進行初始化),使該對象具有區別于其他對象的特征。
構造函數在對象被創建時有系統自動調用。
構造函數也是類的成員函數,但是它是一種特殊的成員函數,它除了具有一般成員函數的特征之外,還具有一些特殊的性質:
- 構造函數的名字必須與類名相同。
- 構造函數不指定返回類型,它隱含有返回值,由系統內部使用。
- 構造函數可以有一個或多個參數,因此構造函數可以重載。
- 在創建對象時,系統會自動調用構造函數。
構造函數的格式:
1
2
3
4
5
6<類名>::<構造函數名>(<形參表>):(<初始化列表>);
// 例如
Date::Date(int y,int m,imt d):year(y),month(m),day(d)
{
<構造函數體>
}- 初始化列表:冒號后面是一個構造函數的初始化列表,用于初始化類中的各個數據成員。初始化列表位于構造函數的形參表后面,有一個冒號和逗號分割的若干項構成。初始化列表形式為:成員名(表達式)構成。
- 在構造函數中,初始化優先于賦值。在調用構造函數對類對象初始化時,先執行初始化列表對各個成員進行初始化,再執行構造函數體。
- 初始化順序:初始化列表中各個初始化項的執行順序取決于類成員在類中聲明的順序,而與初始化列表中給出的初始化項的順序無關.
- 數據成員初始化方式:既可以使用初始化列表的方式獲得顯式初值,也可以在獲得默認初值后,再在構造函數體中使用賦值語句將表達式的值負值給數據成員。
析構函數與構造函數的作用幾乎正好相反,它用來完成對象被刪除前的以前清理工作,也就是專門做掃尾工作的。一般情況下,析構函數在對象的生存周期即將結束的時候由系統自動調用。它的調用完成之后,對象也就消失了,相應的內存空間也就被釋放。
析構函數也是類中的一種成員函數,具有以下特性:
- 析構函數名是在類名前加一個取反(求補)符號~。
- 析構函數不指定返回類型,它隱含有返回值,由系統內部使用。
- 析構函數沒有參數,因此析構函數不能重載,一個類中只能定義一個析構函數。
- 在撤銷對象時,系統會自動調用析構函數。
注意析構函數的調用順序與構造函數的調用順序是完全相反的。
默認構造函數和默認析構函數
默認構造函數就是調用時不必提供參數的構造函數,它的函數名與類名相同,它的參數表或者為空,或者它所有參數都具有默認值。
如果類中定義了一個默認的構造則使用該函數,如果一個類中沒有定義任何構造函數,編譯器將會生成一個不帶參數的公有默認構造函數,它的定義格式:<類名>::<類名>(){},同理公有的默認析構函數格式是:<類名>::~<類名>(){}。
復制構造函數
復制構造函數的功能:用一個已知的對象去初始化一個正在創建的對象。
類中還有一種特殊的構造函數叫做復制構造函數,它用一個已知的對象初始化出一個正在創建的同類對象,復制構造函數的一般格式如下:
1
2
3
4<類名>::<類名>(const<類名>& <引用對象名>)
{
//復制構造函數體
}復制構造函數具有的特點:
也是一種構造函數,因此函數名與類名相同,并且不能指定函數返回類型。
只有一個參數,是對同類的某個對象的引用。
每一個類中都必須有一個復制構造函數。如果類中沒有聲明復制構造函數,編譯器會自動生成一個具有上述形式的公有復制構造函數。
通常情況下,復制構造函數在下面情況下回被調用:
用類的一個已知的對象去初始化該類的另一個正在被創建的對象。
采用傳值調用方式時,對象作為函數實參傳遞給函數形參。
對象作為函數返回值。
自由存儲對象
定義:到目前為止,在為程序中定義的對象分配內存空間時采用的都是“靜態存儲方式”,在編譯時就能確定所占存儲空間的大小,而與之相對的動態存儲分配技術則可以保證在程序運行過程中按照實際需要申請適量的內存,使用結束后在進行釋放。這種程序運行過程中根據需要可以隨時建立或刪除的對象成為自由存儲對象。建立和刪除工作分別由運算符new和delete完成。
用new創建單個對象時,要根據參數調用相應的構造函數,在用new創建對象數組時,會調用默認構造函數,用delete刪除對象時,要調用析構函數。
在對自由存儲對象調用構造函數和析構函數時,要注意,這時的調用時顯式進行的,調用的順序取決于new和delete運算符的順序。這時析構函數的執行順序不一定與構造函數的執行順序嚴格相反,但對象數組中各個元素的構造和析構順序仍然是相反的。
this指針
C++中提供一種特殊的對象指針——this指針,它是成員函數所屬對象的指針,它指向類對象的地址。成員函數可以通過這個指針知道自己屬于哪一個對象。
this是一個隱含的指針,它隱含于每一個類的非靜態成員函數中,它明確地表示出了成員函數當前操作的數據所屬的對象。當一個對象調用成員函數時,編譯程序先將對象的地址賦值給this指針,然后調用成員函數。每次成員函數存取數據成員時,會隱含使用this指針。
靜態成員
對于類中的非靜態成員,每一個類對象都擁有一個副本,即每個對象的同名數據成員可以分別存儲不同的數值,這是保證每個對象擁有區別于其他對象的特征的需求。
類中的靜態成員則是解決同一個類不同對象之間的數據和函數共享問題的。靜態成員的特性是不管這個類創建了多少個對象,它都只有一個副本,這個副本由所有屬于這個類的對象共享。靜態成員表示整個類范圍的信息,其聲明以static關鍵字開始,包括靜態數據成員和靜態成員函數。
靜態數據成員
示例
1
2
3
4
5
6class MyClass
{
private:
int a,b,c;
static int sum; //私有靜態數據成員
};說明
sum是靜態數據成員,它被MyClass類的所有對象共享,但它不屬于MyClass類的任何一個對象,它的作用域是類范圍。
靜態數據成員在每個類對象中并不占有存儲空間,它只是在每個類中分配有存儲空間,供所有對象公用。靜態數據成員的值對每一個對象都是一樣的。
初始化:靜態數據成員具有靜態生存周期,必須對它進行初始化。靜態數據成員初始化的一般格式如下。
1 <數據類型> <類名>::<靜態數據成員名>=<初始值> 對靜態數據成員初始化時注意:
- 由于在類的聲明中僅僅是對靜態數據成員進行了引用性聲明,因此必須在文件作用域的某個地方對靜態數據成員進行定義并初始化,即應在類體外對靜態數據成員進行初始化(靜態數據成員的初始化與它的訪問控制權限無關)。
- 靜態數據成員初始化時前面不需要加static關鍵字,以免與一般靜態變量或對象混淆。
- 由于靜態數據成員是類的成員,因此在初始化時必須使用作用域運算符(::)限定它所屬的類。
靜態成員函數
公有的靜態成員可以直接訪問,但是私有的或保護的靜態數據成員卻必須通過公用的接口進行訪問,一般將這個公用的接口定義為靜態成員函數。
使用static關鍵字聲明的成員函數就是靜態成員函數,靜態成員函數也是屬于整個類而不屬于類中的某個對象,它是該類的所有對象共享的成員函數。
靜態成員函數既可以在類體內進行定義,也可以在類體外定義。當在類體外定義時,要注意不能使用static關鍵字作為前綴。
由于靜態成員函數在類中只有一個副本,因此它訪問對象的成員時收到一些限制:靜態成員函數可以直接訪問類中說明的靜態成員,但不能直接訪問類中說明的非靜態成員;若要訪問非靜態成員時,必須通過參數傳遞的方式得到相應的對象,在通過對象進行訪問。
公有的靜態成員既可以直接使用作用域運算符通過類名進行訪問,也可以通過類的任何對象進行訪問,但是建議使用前者訪問,即:
1
2
3<類名>::<靜態數據成員名>
或
<類名>::<靜態數據成員名>(<參數表>)由于靜態成員在該類的任何對象被建立之前就存在,因此靜態成員可以在程序內部不依賴于任何對象被訪問,即使沒有建立該類的任何一個對象時也可以使用作用域運算符通過類名訪問類的共有靜態成員。
常成員
存在的意義:雖然數據隱藏保證了數據的安全性,但各種形式的數據共享卻又不同程度地破壞了數據的安全性。因此,對于既需要共享又需要防止改變的數據應該定義為常量進行保護,以保證它在整個程序運行期間是不可改變的。
這些常量需要使用const修飾符進行定義。const關鍵字不僅可以修飾類對象本身,也可以修飾類對象的成員函數和數據成員,分別稱為常對象、常成員函數和常數據成員。
常對象
使用const關鍵字修飾符的對象稱為常對象,其定義格式如下:
1
2
3<類名> const <對象名>
或
const <類名> <對象名>常對象在定義時必須進行初始化,而且不能被更新。
常成員函數
使用const關鍵字說明的成員函數被稱為常成員函數,常成員函數的說明格式如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29<返回類型> <成員函數名>(<參數表>) const;
```
- const是函數類型的一個組成部分,因此在函數實現部分也要帶有const關鍵字;如果在定義常成員函數時丟失了const關鍵字,程序會產生錯誤。
- 常成員函數也不能更新對象的數據成員,否則也會產生錯誤。
- 當成員函數時常成員函數時,常對象和一般對象都是可以調用它的,但是對于一般成員函數,則只有一般對象可以調用,常對象不能調用一般成員函數,如果調用它將會產生錯誤。
- const關鍵字可以用于參與對重載函數的區分。重載的原則是:常對象調用常成員函數,一般對象調用一般成員函數。此處需要注意的是:當類中只有一個常成員函數時,一般對象也可以調用該常成員函數。但當兩個同名的一般成員函數和常成員函數同時存在時,遵循上述重載原則。
- 常數據成員
- 使用const說明的數據成員稱為常數據成員。常數據成員的定義與一般常量的定義方式相同,只是它的定義必須出現在類體內。
- 常數據成員同樣也必須進行初始化,并且不能被更新。但常數據成員的初始化只能通過**構造函數**的成員初始化列表顯示進行。
## 友元
- 存在的意義:類具有數據**封裝和隱藏**的特性,只有類的成員函數才能訪問類的私有成員和保護成員,外部函數只能訪問類的公有成員。但是在某些情況下,需要在類的外部訪問類的私有成員和保護成員。這時,如果通過公有成員函數進行訪問,由于參數傳遞、類型檢查和安全性檢查等需要時間上的開銷,并影響程序的**運行效率**。為了解決這個問題,引入友元。
- **友元:可以在類外部直接訪問類的私有成員和保護成員,提高程序的運行效率。**
- 友元提供了不同類或對象的成員函數之間、類的成員函數與一般函數之間進行數據共享的機制。對于一個類,可以利用`friend`關鍵字將一般函數、其他類的成員函數或者是其他類聲明為該類的友元,使得這個類本來隱藏的信息(包括私有成員或保護成員)可以被友元所訪問。
- 如果友元是一般成員函數或者類的成員函數,稱為友元函數;如果友元是一個類,則成為友元類,友元類的所有成員函數都被稱為友元函數。
- **友元函數**
- 友元函數不是當前類的成員函數,而是**獨立于當前類的外部函數**(包括普通函數和其他類的成員函數),但它可以訪問該類的所有成員,包括私有成員、保護成員和公有成員。
- 友元函數要在類定義時聲明,聲明時要在其函數名前加上**關鍵字friend**。 該聲明可以放在**公有部分,也可以放在私有部分和保護部分**。友元函數的定義通常在類外部。
> 例子#include
using namespace std;class DATE{
DATE(int y=2003,int m=1,int d=1):year(y),month(m),day(d){ } friend void DateTime(const DATE &d,const TIME &t);
public:private:
int year,month,day;};
void DateTime(const DATE &d){
cout<<”Now is:”<<d.year<<”.”<<d.month<<”.”<<d.day<<”.”<<endl;
}1
2
3
4
5
6
7
8
> 由于采用friend將外部函數DateTime設置為DATE類友元函數,所以這個函數能夠直接訪問類的成員變量。
- **友元類**
友元類除了可以是函數外,還可以是類,即一個類可以作為另一個類的友元,稱為友元類。友元類的所有成員函數都是另一個類的友元函數,都可以訪問另一個類的所有成員函數和成員變量。
友元類的說明方法:friend <類名> // 友元類類名
1
2
3
4
5
6
7
## 對象數組
- **定義**:對象數組是指數組元素為對象的數組,該數組的每一個元素都是同一個類的對象。
- 對象數組定義的格式如下:<類名> <數組名>[<大小>]…
1
2
- 使用對象數組成員的一般格式:<數組名>[<下標>].<成員名>
`
成員對象
定義:類的數據成員可以是簡單類型或自定義類型的變量,也可以是類類型的對象。因此,可以利用已定義的類來構造新的類,使得一些復雜的類可以有一些簡單的類組合而成。當類的數據成員為其他類的對象時,這個對象被稱為成員對象。
初始化,當類中出現了成員對象時,該類的構造函數要包含對成員對象的初始化,成員對象的初始化工作也是在成員初始化列表中完成的。
構造順序:建了一個類的對象時,要調用它的構造函數對類對象初始化,此時應先執行初始化列表,對各個成員進行初始化,再執行當前類的構造函數體。如果類中包含有成員對象,注意要根據初始化的參數調用成員對象的構造函數對其進行初始化。
成員對象初始化時,根據初始化列表的特點可知,類中有多個成員對象時,要按照定義成員對象的順序建立各個子對象(即成員對象構造函數的執行順序僅與成員對象在類中聲明的順序有關,而與成員初始化列表中給出的成員對象的順序無關)。如果在構造函數的成員初始化列表中沒有給出對成員對象的初始化,則表示使用成員對象的默認構造函數,如果成員對象所在的類沒有默認構造函數,將產生錯誤。
第七章 繼承和派生
概念
繼承是面向對象程序設計的一個重要特性,是軟件復用的一種形式,它允許在原有類的基礎上創建新的類。新類可以從一個或多個原有類中繼承函數和數據,并且可以重新定義或增加新的數據和函數,從而形成類的層次或等級。
派生類與基類成員的訪問
派生類的構造函數和析構函數
多繼承和虛基類
*子類型關系
虛函數與多態性
第八章 運算符重載
運算符函數與運算符重載
典型運算符的重載
*運算符重載應注意的幾個問題
第九章 模板
函數模板
類模板
第十章 C++流
C++流的概念
輸入輸出的格式控制
文件流
總結
以上是生活随笔為你收集整理的C++等级考试知识点总结的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 法宣在线自动考试
- 下一篇: C++初始编程及相关的问题总结