一,、C++教程前言介紹
https://blog.csdn.net/weixin_55305220/article/details/118668036?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1.pc_relevant_antiscanv2&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1.pc_relevant_antiscanv2&utm_relevant_index=1 這部C++教程是大全教程,。其內(nèi)容涵蓋了C++語言的基本語法、面向?qū)ο?/a>的概念和程序設計方法,、數(shù)據(jù)結(jié)構(gòu)基礎(chǔ),、模板和泛型程序設計簡介。從零開始,、由淺入深,、層層遞進、細致而又詳盡地講解C++這門大型編程語言,。
可以關(guān)注 微 信 公 眾 號 “C和C加加” 回復 “ZXC” 即可獲取 詳細教程 和 PDF版,!
二、基本語法
- 對象-對象具有狀態(tài)的行為,。對象是類的實例,。
- 類-類可以定義為對象行為,、狀態(tài)的模版。
- 方法-從基本上講,,一個方法表示一種行為,,一個類可以包含多種方法。
- 變量
1,、注釋
2,、關(guān)鍵字
3、標識符
標識符是用來標識變量,、函數(shù),、類、模塊,,或任何其他用戶自定義項目的名稱,。一個標識符以字母 A-Z 或 a-z 或下劃線 _ 開始,后跟零個或多個字母,、下劃線和數(shù)字(0-9),。
標識符內(nèi)不允許出現(xiàn)標點字符,比如 @,、& 和 %,。C++ 是區(qū)分大小寫的編程語言。
三,、數(shù)據(jù)類型
1,、第一個C++程序
2、基本數(shù)據(jù)類型
七種基本的C++數(shù)據(jù)類型:bool,、char,、int、float,、double,、void、wchar_t
類型修飾符:signed,、unsigned,、short、long
注:一些基本類型可以使用一個或多個類型修飾符進行修飾,,比如:signed short int簡寫為short,、signed long int 簡寫為long。
3,、數(shù)據(jù)類型在不同系統(tǒng)中所占空間大小
這個與機器,、操作系統(tǒng)、編譯器有關(guān)。比如同樣是在32bits的操作系統(tǒng)系,,VC++的編譯器下int類型為占4個字節(jié),;而tuborC下則是2個字節(jié)。
原因:
c/c++規(guī)定int字長和機器字長相同
操作系統(tǒng)字長和機器字長未必一致
編譯器根據(jù)操作系統(tǒng)字長來定義int字長
4,、typedef聲明
5,、枚舉類型
C++中的一種派生數(shù)據(jù)類型,它是由用戶定義的若干枚舉常量的集合,;枚舉元素是一個整型,,枚舉型可以隱式的轉(zhuǎn)換為int型,int型不能隱式的轉(zhuǎn)換為枚舉型,。
如果枚舉沒有初始化, 即省掉"=整型常數(shù)"時, 則從第一個標識符開始;
默認情況下,,第一個名稱的值為 0,第二個名稱的值為 1,,第三個名稱的值為 2,,以此類推。但是,,您也可以給名稱賦予一個特殊的值,,只需要添加一個初始值即可。
例如:
6 ,、常量及符號
(1)整型常量
整型常量可以分為有符號整型常量和無符號整型常量
八進制:以0開頭,,即以0作為八進制數(shù)的前綴,每位取值范圍是0~7,,八進制數(shù)通常是無符號數(shù)。
例如:016,、0101,、0128都是合法的八進制數(shù) 十六進制:以0x或者0X開頭,其數(shù)碼取值范圍0 ~ 9,,以及A ~ F或者a ~ f
例如:0X2A1,、0XC5、0XFFFF都是合法的16進制數(shù)
(2)實型常量
小數(shù)表示法:由整數(shù)部分和小數(shù)部分組成,,整數(shù)部分和小數(shù)部分每位取值范圍是0~9,,例如:0.0、3.25,、0.00596,、2.0 指數(shù)表示法:指數(shù)部分以符號"e"或者"E"開始,但必須是整數(shù),,并且符號"e"或"E"兩邊都必須有一個數(shù),,例如:1.2e20和-3.4e-2
(3)字符常量
字符常量是單引號括起來的字符,例如:'a'和'?'都是合法字符常量。字符'a'的ASCII碼值是97,,字符'A'的ASCII碼值是41,,字符'?'的ASCII碼值是63
轉(zhuǎn)義字符是特殊的字符常量,使用時以字符串’'代表開始轉(zhuǎn)義,,和后面不同的字符表示轉(zhuǎn)義的字符,。轉(zhuǎn)義字符表如下所示:
(4)字符串常量
是由一對雙引號括起來的零個或多個字符序列,例如:“welcome to our school”,、“hello world”,。""可以表示一個空字符串。
字符常量’A’和字符串常量"A"是不同的,,字符串常量"A"是由'A'和'\0'兩個字符組成的,,字符串長度是2,字符串常量'A'只是一個字符,,沒有長度,。
(5)其他常量
- 布爾常量:布爾常量只有兩個,一個是true,,表示真,;另一個是false,表示假,。
- 枚舉常量:枚舉型數(shù)據(jù)中定義的成員也是常量,,這將在后文介紹。
- 宏定義常量:通過#define宏定義的一些值也是常量,。例如:define PI3.1415,。其中PI就是常量。
7,、變量
變量其實只不過是程序可操作的存儲區(qū)的名稱,。C++ 中每個變量都有指定的類型,類型決定了變量存儲的大小和布局,,該范圍內(nèi)的值都可以存儲在內(nèi)存中,,運算符可應用于變量上。
(1)標識符:是用來對C++程序中的常量,、變量,、語句標號以及用戶自定義函數(shù)的名稱進行標識的符號。 標識符命名規(guī)則:
- 有字母,、數(shù)字及下劃線組成,,且不能以數(shù)字開頭。
- 大寫和小寫字母代表不同意義,。
- 不能與關(guān)鍵字同名
- 盡量“見名知義”,,應該受一定規(guī)則的約束,。
- 不合法的標識符:6A、ABC*,、case(保留字)
c++保留關(guān)鍵字,,如圖所示:
(2)變量與變量說明:變量使用前一定要定義或說明,變量聲明的一般形式如下:[修飾符] 類型 變量名標識符 ,;
類型是變量類型的說明符,,說明變量的數(shù)據(jù)類型。修改師傅是任選的,,可以沒有,。
(3)整型變量:整型變量可以分為短整型、整型和長整型,,變量類型說明符分別是short,、int、long,。根據(jù)是否有符號還可分為以下6種,。
- 整型 [signed] int
- 無符號整型 unsigned [int]
- 有符號短整型 [signed] short [int]
- 無符號短整型 unsigned short [int]
- 有符號長整型 [signed] long [int]
- 無符號長整型 unsigned long [int]
(4)實型變量:又稱為浮點型變量,變量可分為單精度(float),、雙精度(double)和長雙精度(long double)三種,。
(5)變量賦值:變量值是動態(tài)改變的,每次改變都需要進行賦值運算,。變量賦值的形式如下:變量名標識符 = 表達式 ,,例如:
(6)變量賦初值:可以在聲明變量的時候就把數(shù)據(jù)賦給變量,這個過程叫變量賦初值,,賦初值的情況有以下幾種:
- int x=5;:表示定義x為有符號的基本整型變量,,賦初值為5
- int x,y,,z=6;:表示定義x,、y、z為有符號的基本整型變量,,z賦初值為6
- int x=3,y=3,,z=3;:表示定義x,、y、z為有符號的基本整型變量,,且賦予的初值均為3
(7)字符變量:
- 一個字符類型,,即可以字符形式輸出,也可以整數(shù)類型輸出:
- 允許對字符數(shù)據(jù)進行算術(shù)運算,,此時就是對它們的ASCII碼值進行算術(shù)運算:
(8)變量的作用域
局部變量:在函數(shù)或一個代碼塊內(nèi)部聲明的變量,,稱為局部變量。它們只能被函數(shù)內(nèi)部或者代碼塊內(nèi)部的語句使用。 全局變量:在所有函數(shù)外部定義的變量(通常是在程序的頭部),,稱為全局變量,。全局變量的值在程序的整個生命周期內(nèi)都是有效的。
局部變量和全局變量的名稱可以相同,,但是在函數(shù)內(nèi),,局部變量的值會覆蓋全局變量的值。 當局部變量被定義時,,系統(tǒng)不會對其初始化,;定義全局變量時,系統(tǒng)會自動初始化值:int float double 0,,char ’\0',,指針 NULL
8、自定義數(shù)據(jù)類型
(1)結(jié)構(gòu)體
結(jié)構(gòu)體可以包含不同數(shù)據(jù)類型的結(jié)構(gòu),。
定義結(jié)構(gòu)體的一般形式
結(jié)構(gòu)體變量名的定義和初始化:
//定義結(jié)構(gòu)體同時聲明結(jié)構(gòu)體變量名 [struct] 結(jié)構(gòu)體類型名 變量名; }p1 = {2019,24,"heiren"}, p1 = { 2020,24,"heiren" }; struct person p1 = { 2019,24,"heiren" }, p1 = { 2020,24,"heiren" }; }p1 = {2019,24,"heiren"}, p1 = { 2020,24,"heiren" };
結(jié)構(gòu)體變量的使用:
- 具有相同類型的結(jié)構(gòu)體變量可以進行賦值運算,,但是不能輸入輸出
- 對結(jié)構(gòu)體變量的成員引用:
結(jié)構(gòu)體變量名.成員名 - 指向結(jié)構(gòu)體的指針變量引用格式:
指針變量名->成員名; 結(jié)構(gòu)體數(shù)組的定義,初始化和使用與結(jié)構(gòu)體變量,、基本類型數(shù)組相似
}p[2] ={ {2019,24,"heiren"}, { 2020,24,"heiren" }};//可以不指定數(shù)組元素個數(shù)
結(jié)構(gòu)體作為函數(shù)傳遞有三種:值傳遞,,引用傳遞,指針傳遞
結(jié)構(gòu)體大小和字節(jié)對齊 現(xiàn)代計算機中內(nèi)存空間都是按照byte劃分的,,從理論上講似乎對任何類型的變量的訪問可以從任何地址開始,,但實際情況是在訪問特定類型變量的時候經(jīng)常在特 定的內(nèi)存地址訪問,這就需要各種類型數(shù)據(jù)按照一定的規(guī)則在空間上排列,,而不是順序的一個接一個的排放,,這就是對齊. 為什么需要字節(jié)對齊?各個硬件平臺對存儲空間的處理上有很大的不同,。一些平臺對某些特定類型的數(shù)據(jù)只能從某些特定地址開始存取,。比如有些平臺每次讀都是從偶地址開始,如果一個int型(假設為32位系統(tǒng))如果存放在偶地址開始的地方,,那么一個讀周期就可以讀出這32bit,,而如果存放在奇地址開始的地方,就需要2個讀周期,,并對兩次讀出的結(jié)果的高低字節(jié)進行拼湊才能得到該32bit數(shù)據(jù),。 三個個概念:
自身對齊值:數(shù)據(jù)類型本身的對齊值,結(jié)構(gòu)體或類的的自身對齊值是其成員中最大的那個值,,例如char類型的自身對齊值是1,,short類型是2; 指定對齊值:編譯器或程序員指定的對齊值,,32位單片機的指定對齊值默認是4,; 有效對齊值:自身對齊值和指定對齊值中較小的那個,。 字節(jié)對齊的三個準則 結(jié)構(gòu)體變量的首地址能夠被其有效對齊值的大小所整除 結(jié)構(gòu)體的總大小為結(jié)構(gòu)體有效對齊值的整數(shù)倍。 結(jié)構(gòu)體每個成員相對于結(jié)構(gòu)體首地址的偏移量都是有效對齊值的整數(shù)倍,。 可以通過#pragma pack(n)來設定變量以n字節(jié)對齊方式
(2)公用體(union)
幾個不同的變量共享同一個地址開始的內(nèi)存空間,。
成員類型可以是基本數(shù)據(jù)類型,也可以是構(gòu)造數(shù)據(jù)類型,。 公用體變量初始化時,,只能對第一個成員賦值。 公用體變量所占的內(nèi)存長度等于最長的成員長度,。 公用體變量在一個時刻只能一個成員發(fā)揮作用,,賦值時,成員之間會互相覆蓋,,最后一次被賦值的成員起作用,。 定義:
初始化
引用
cout << x.i << " " << x.f << " " << x.c << endl;//12 1.68156e-44 cout << x.i <<" "<< x.f << " " << x.c << endl;//99 1.38729e-43 c
9、數(shù)據(jù)輸入與輸出
(1)控制臺屏幕
(2)操作控制
在頭文件iomanip.h中定義了一些控制流輸出格式的函數(shù),,默認情況下整型數(shù)按十進制形式輸出,,也可以通過hex將其設置為十六進制輸出。流操作的控制具體函數(shù)如下
四,、運算符與表達式
1,、運算符
(1)算術(shù)運算符:算術(shù)運算主要指常用的加(+)、減(-),、乘(*),、除(/)四則運算,算術(shù)運算符中有單目運算符和雙目運算符,。
(2)關(guān)系運算符
關(guān)系運算符主要是對兩個對象進行比較,,運算結(jié)果是邏輯常量真或假。
(3)邏輯運算符
邏輯運算符是對真和假這兩種邏輯值進行運算,,運算后的結(jié)果仍是一個邏輯值
(4)賦值運算符
(5)位運算符
(6)移位運算符
(7)sizeof運算符
(8)條件運算符
(9)逗號運算符
(10)運算符優(yōu)先級
(11) 運算符重載
所謂重載,,就是賦予新的含義。函數(shù)重載(Function Overloading)可以讓一個函數(shù)名有多種功能,,在不同情況下進行不同的操作,。運算符重載(Operator Overloading)也是一個道理,同一個運算符可以有不同的功能。
運算符重載是通過函數(shù)實現(xiàn)的,它本質(zhì)上是函數(shù)重載。 允許重載的運算符
不允許重載的運算符
重載運算符遵循的規(guī)則:
- 不可以自己定義新的運算符,,只能對已有的C++運算符重載。
- 不能改變運算符運算對象的個數(shù)。
- 不能改變運算符的優(yōu)先級和結(jié)合性
- 應與標準類型運算功能相似,避免影響可讀性。
一般格式:
函數(shù)類型 operator運算符(參數(shù)列表) //舉個栗子:定義一個向量類,通過運算符重載,可以用+進行運算。 Vector3(double x,double y,double z); Vector3 operator+(const Vector3 &A)const; Vector3::Vector3() :m_x(0.0), m_y(0.0), m_z(0.0) {} Vector3::Vector3(double x, double y,double z) : m_x(x), m_y(y), m_z(z) {} Vector3 Vector3::operator+(const Vector3 &A) const B.m_x = this->m_x + A.m_x; B.m_y = this->m_y + A.m_y; B.m_z = this->m_z + A.m_z; void Vector3::display()const cout<<"(" << m_x << "," << m_y << "," << m_z << ")" << endl;
運算符重載的形式有兩種:重載函數(shù)作為類的成員,,重載函數(shù)作為類的友元函數(shù) 根據(jù)運算符操作數(shù)的不同:雙目運算符作為類成員函數(shù),單目運算符作為類的成員函數(shù),,雙目運算符作為類的友員函數(shù),,單目運算符作為類的友元函數(shù),。
雙目運算符作為友元函數(shù)時需要制定兩個參數(shù),。 運算符重載函數(shù)作為類成員函數(shù)可以顯式調(diào)用。
常用運算符的重載
2,、表達式
(1)算數(shù)表達式
(2)關(guān)系表達式
(3)條件表達式
(4)賦值表達式
(5)邏輯表達式
(6) 逗號表達式
五,、語法結(jié)構(gòu)
1,、while循環(huán)
while(conditon)//0為false,非0為true
2、do…while循環(huán)
3,、while與do…while比較
4,、for
for(init;conditon;increment)//0為false,非0或什么也不寫為true
- init首先被執(zhí),且只會執(zhí)行一次,,也可以不寫任何語句。
- 然后會判斷conditon,true執(zhí)行循環(huán)主體,,false跳過循環(huán)
- 執(zhí)行完循環(huán)主體,執(zhí)行increment,跳到2
int array[5] = { 11, 22, 33, 44, 55 }; // auto 類型也是 C++11 新標準中的,,用來自動獲取變量的類型
- for each
STL中的for增強循環(huán)。
5,、判斷結(jié)構(gòu)
statement;//如果expr為true將執(zhí)行的語句塊 statement1;// 如果expr為true將執(zhí)行的語句塊 statement2;// 如果expr為false將執(zhí)行的語句 statement1;// 如果expr1為true將執(zhí)行的語句塊 statement2;// 如果expr2為true將執(zhí)行的語句塊 statementElse;// 當上面的表達式都為false執(zhí)行的語句塊
case constant-expression : case constant-expression : // 您可以有任意數(shù)量的 case 語句
每個case后滿的常量表達式必須各不相同,。 case語句和default語句出現(xiàn)的順序?qū)?zhí)行結(jié)果沒有影響。 若case后沒有break,執(zhí)行完就不會判斷,,繼續(xù)執(zhí)行下一個case語句,。直到遇到brerak。 default后面如果沒有case,,則break可以省略 多個case可以用一組執(zhí)行語句
6,、循環(huán)控制
7、循環(huán)嵌套
8,、三元運算符
//如果 Exp1 為真,,則計算 Exp2 的值,,結(jié)果即為整個 ? 表達式的值。如果 Exp1 為假,,則計算 Exp3 的值,,結(jié)果即為整個 ? 表達式的值
9、預處理命令
預處理程序(刪除程序注釋,,執(zhí)行預處理命令等)–>編譯器編譯源程序
- 宏定義:
#define 標識符 字符串 - 文件包含:
#include<filename> 或者#include“filename” - 條件編譯
//如果標識符被#define定義過,,執(zhí)行程序段1,否則執(zhí)行程序段2 //如果標識符沒有被#define定義過,,執(zhí)行程序段1,,否則執(zhí)行程序段2 //如果表達式為true,執(zhí)行程序段1,,否則執(zhí)行程序段2
六,、數(shù)組和指針
1、一維數(shù)組
初始化的形式:數(shù)據(jù)類型 數(shù)組名[常量表達式] = {初值表}; 為數(shù)組的某一個元素賦值:數(shù)組名[下標] =值 (下標從0開始) 數(shù)組的引用:數(shù)組名[下標]
- 初始化數(shù)組時,,可以只給部分數(shù)組元素賦值
- 對全部元素數(shù)組賦值時,,可以不指定數(shù)組長度,編譯系統(tǒng)會根據(jù)初值個數(shù)確定數(shù)組的長度,。
- static型數(shù)組元素不賦初值,系統(tǒng)會自動默認為0,。
2,、二維數(shù)組
定義一維數(shù)組的形式:數(shù)據(jù)類型 數(shù)據(jù)名[常量表達式1][常量表達式2] 初始化的形式:數(shù)據(jù)類型 數(shù)組名[常量表達式1] [常量表達式2]= {初值表}; 為數(shù)組的某一個元素賦值:數(shù)組名[行下標][列下標] =值(下標從0開始) 數(shù)組的引用:數(shù)組名[行下標][列下標]
將所有數(shù)據(jù)寫在一個花括號內(nèi),自動按照數(shù)組元素個數(shù)在內(nèi)存中排列的順序賦值 可對部分元素賦值,,其余元素的值自動取0. 定義初始化數(shù)組時,,可以省略第一維的長度,第二維不能省,,系統(tǒng)會自動確認行數(shù)
3,、字符數(shù)組
char類型的數(shù)組,在字符數(shù)組中最后一位為’\0’)時,,可以看成時字符串,。在C++中定義了string類,在Visual C++中定義了Cstring類,。 字符串中每一個字符占用一個字節(jié),,再加上最后一個空字符。
4,、指針
指針是一個變量,,其值為另一個變量的地址。即內(nèi)存位置的直接地址,。 聲明的一般形式:
- 數(shù)據(jù)類型是指針變量所指向的變量的數(shù)據(jù)類型,,*表示其后的變量為指針變量
double *dp; //double 型的指針
指針變量的初始化:
- &是取地址運算符,,&變量名表示變量的地址。
- 變量的數(shù)據(jù)類型必須于指針變量的數(shù)據(jù)類型一致,。
- 為了安全起見,,有時會把指針初始化為空指針(NULL或0)
數(shù)據(jù)類型 *指針變量名 = &變量名;
指針變量的引用:
- & 取地址符 * 指針運算符(間接運算符),其后是指針變量,,表示該指針變量所指向的變量,。
- & *的優(yōu)先級是相同的,結(jié)合方式都是自左向右,。比如 &*p等價于&(*p),。
指針運算(地址運算)
算術(shù)運算(移動指針運算):加減,自增自減,。 p+n運算得到的地址是p+n*sizeof(數(shù)據(jù)類型),。 兩個相同數(shù)據(jù)類型的指針可以進行加減運算,一般用于數(shù)組的操作中,。 關(guān)系運算:指針指向同一串連續(xù)存儲單元才有意義,,比如數(shù)組。與0比較,,判斷是不是空指針,。 賦值運算:變量地址賦值給指針變量,數(shù)組元素地址賦值給指針變量,,指針變量賦值給其他指針變量,。
int *p1 = &arr[2],*p2 = &arr[5]; len = p2-p1;//arr[2] 和arr[5]之間的元素個數(shù) 3
new和delete運算符
- new-為變量分配內(nèi)存空間;
- 可以通過判斷new返回的指針的值,,判斷空間是否分配成功,。
- delete-釋放空間
指針變量 = new 數(shù)據(jù)類型(初值); delete[] 指針變量;//釋放為多個變量分配的地址 for (int i = 0; i < 10;i++)
5、指針與數(shù)組
6,、數(shù)組與new(動態(tài)創(chuàng)建數(shù)組)
一維數(shù)組
int* arr1 = new int[2];//delete []arr1; int* arr2 = new int[3]{ 1,2 };//delete []arr2
二維數(shù)組
int** arr3 = new int*[2];//delete []arr3 for (int i = 0; i < 10; ++i) arr3[i] = new int[3]; // delete []arr3[i] int* arr4 = new int[m*n];//數(shù)據(jù)按行存儲 delete []arr3
7,、指針與字符串
- 字符串數(shù)組名:
char ch[] = "heiren";char *p = ch; - 字符串:
char *p = "heiren"; - 指針賦值運算:
char * p;p = "Heiren"; 指針與函數(shù),指針可以作為函數(shù)的參數(shù),,也可以作為函數(shù)的返回值,。
8、指向函數(shù)的指針
9,、引用
引用可以看做是數(shù)據(jù)的一個別名,,通過這個別名和原來的名字都能夠找到這份數(shù)據(jù),類似于window中的快捷方式,。
引用不占內(nèi)存空間,,必須在定義的同時初始化,且不能再引用其他數(shù)據(jù),。 引用在定義時需要添加&,,在使用時不能添加&,,使用時添加&表示取地址 引用型變量聲明:數(shù)據(jù)類型 &引用名 = 變量名;
int &b = a;//a和b表示相同的變量,具有相同的地址,。
引用可以作為函數(shù)參數(shù),,也可以作為函數(shù)返回值。
void swap(int &r1, int &r2) { cout << a << " "<<b << endl;//13 13
將引用作為函數(shù)返回值時不能返回局部數(shù)據(jù)的引用,,因為當函數(shù)調(diào)用完成后局部數(shù)據(jù)就會被銷毀,。 函數(shù)在棧上運行,函數(shù)掉用完,,后面的函數(shù)調(diào)用會覆蓋之前函數(shù)的局部數(shù)據(jù),。
test();//函數(shù)調(diào)用,覆蓋之前函數(shù)的局部數(shù)據(jù) cout << a << " "<<b <<" "<< c<<endl;//14 -858993460 -858993460
七,、函數(shù)
1,、函數(shù)聲明與定義
- 函數(shù)類型-函數(shù)的返回值類型;函數(shù)名-必須符合C++標識符命名規(guī)則,,后面必須跟一對括號,;函數(shù)體-實現(xiàn)函數(shù)功能的主題部分;參數(shù)列表-函數(shù)名后面的括號內(nèi),,用于向函數(shù)傳遞數(shù)值或帶回數(shù)值,。
- 函數(shù)聲明中,參數(shù)名可以省略,,參數(shù)類型和函數(shù)的類型不能省略,。
- 函數(shù)聲明可以放在主調(diào)函數(shù)內(nèi)部,放在調(diào)用語句之前,;也可以放在主調(diào)函數(shù)外,如果位于所有定義函數(shù)之前,,后面函數(shù)定義順序任意,,各個主調(diào)函數(shù)調(diào)用也不必再做聲明
- 當函數(shù)定義在前,函數(shù)調(diào)用災后,,可以不用函數(shù)聲明,。
后兩條總結(jié)一下就是:調(diào)用函數(shù)前,程序得知道有這個函數(shù),,聲明就是提前讓程序知道有這么的玩意
函數(shù)聲明:
函數(shù)類型 函數(shù)名(參數(shù)列表); int max(int a,int b);//聲明函數(shù)時,,a,b可以省略
函數(shù)定義:
函數(shù)類型 函數(shù)名(參數(shù)列表)
2、函數(shù)參數(shù)以及返回值
- 形參:函數(shù)定義后面括號里的參數(shù),,函數(shù)調(diào)用前不占內(nèi)存,。
- 實參:函數(shù)調(diào)用括號里的參數(shù),可以是常量,,變量或表達式等,。
形參和實參必須個數(shù)相同,、類型一致,順序一致,,函數(shù)傳遞方式:傳值,,指針,引用
3,、函數(shù)調(diào)用
- 函數(shù)可以單獨作為一個語句使用,。有返回值的函數(shù),可將函數(shù)調(diào)用作為語句的一部分,,利用返回值參與運算,。
函數(shù)調(diào)用形式:參數(shù)傳遞–>函數(shù)體執(zhí)行–>返回主調(diào)函數(shù)
函數(shù)的嵌套調(diào)用:
函數(shù)的遞歸調(diào)用:直接遞歸調(diào)用和間接遞歸調(diào)用
- 一個函數(shù)直接或間接遞歸調(diào)用該函數(shù)本身,稱為函數(shù)的遞歸調(diào)用
- 遞歸和回歸:原問題=>子問題 子問題的解=>原問題的解
return sum + total(sum - 1); cout << "total = " << total(10) << endl;//total = 55
4,、重載函數(shù)
5,、內(nèi)聯(lián)函數(shù)
八、字符串(string)
1,、字符串的定義和初始化
string str2 = "ShangHai";
2,、字符串的處理函數(shù)
string s(str);//生成字符串為str的復制品 string s(str, strbegin,strlen);//將字符串str中從下標strbegin開始、長度為strlen的部分作為字符串初值 string s(cstr, char_len);//以C_string類型cstr的前char_len個字符串作為字符串s的初值 string s(num ,c);//生成num個c字符的字符串 string s(str, stridx);//將字符串str中從下標stridx開始到字符串結(jié)束的位置作為字符串初值 size()和length();//返回string對象的字符個數(shù) max_size();//返回string對象最多包含的字符數(shù),,超出會拋出length_error異常 capacity();//重新分配內(nèi)存之前,,string對象能包含的最大字符數(shù) >,>=,<,<=,==,!=//支持string與C-string的比較(如 str<”hello”)。 使用>,>=,<,<=這些操作符的時候是根據(jù)“當前字符特性”將字符按字典順序進行逐一得 比較,,string (“aaaa”) <string(aaaaa),。 compare();//支持多參數(shù)處理,支持用索引值和長度定位子串來進行比較,。返回一個整數(shù)來表示比較結(jié)果,,返回值意義如下:0:相等 1:大于 -1: insert( size_type index, size_type count, CharT ch );//在index位置插入count個字符ch insert( size_type index, const CharT* s );//index位置插入一個常量字符串 insert( size_type index, const CharT* s, size_type n);//index位置插入常量字符串 insert( size_type index, const basic_string& str );//index位置插入常量string中的n個字符 insert( size_type index, const basic_string& str, size_type index_str, size_type n);//index位置插入常量str的從index_str開始的n個字符 insert( size_type index, const basic_string& str,size_type index_str, size_type count = npos);//index位置插入常量str從index_str開始的count個字符,count可以表示的最大值為npos.這個函數(shù)不構(gòu)成重載 npos表示一個常數(shù),,表示size_t的最大值,,string的find函數(shù)如果未找到指定字符,返回的就是一個npos iterator insert( iterator pos, CharT ch ); iterator insert( const_iterator pos, CharT ch ); void insert( iterator pos, size_type n, CharT ch );//迭代器指向的pos位置插入n個字符ch iterator insert( const_iterator pos, size_type count, CharT ch );//迭代器指向的pos位置插入count個字符ch void insert( iterator pos, InputIt first, InputIt last ); iterator insert( const_iterator pos, InputIt first, InputIt last ); string s1("yuanrui"); // 調(diào)用一次構(gòu)造函數(shù) for( int i = 0; i < s1.size() ; i++ ) for( string::iterator iter = s1.begin();; iter < s1.end() ; iter++) for(string::reverse_iterator riter = s1.rbegin(); ; riter < s1.rend() ; riter++) iterator erase(iterator p);//刪除字符串中p所指的字符 iterator erase(iterator first, iterator last);//刪除字符串中迭代器區(qū)間[first,last)上所有字符 string& erase(size_t pos = 0, size_t len = npos);//刪除字符串中從索引位置pos開始的len個字符 void clear();//刪除字符串中所有字符 string& replace(size_t pos, size_t n, const char *s);//將當前字符串從pos索引開始的n個字符,,替換成字符串s string& replace(size_t pos, size_t n, size_t n1, char c); //將當前字符串從pos索引開始的n個字符,,替換成n1個字符c string& replace(iterator i1, iterator i2, const char* s);//將當前字符串[i1,i2)區(qū)間中的字符串替換為字符串s //tolower()和toupper()函數(shù) 或者 STL中的transform算法 for( int i = 0; i < s.size(); i++ ) transform(s.begin(),s.end(),s.begin(),::tolower); size_t find (constchar* s, size_t pos = 0) const;//在當前字符串的pos索引位置開始,查找子串s,,返回找到的位置索引,,-1表示查找不到子串 size_t find (charc, size_t pos = 0) const;//在當前字符串的pos索引位置開始,查找字符c,,返回找到的位置索引,,-1表示查找不到字符 size_t rfind (constchar* s, size_t pos = npos) const;//在當前字符串的pos索引位置開始,反向查找子串s,,返回找到的位置索引,,-1表示查找不到子串 size_t rfind (charc, size_t pos = npos) const;//在當前字符串的pos索引位置開始,,反向查找字符c,返回找到的位置索引,,-1表示查找不到字符 size_tfind_first_of (const char* s, size_t pos = 0) const;//在當前字符串的pos索引位置開始,,查找子串s的字符,返回找到的位置索引,,-1表示查找不到字符 size_tfind_first_not_of (const char* s, size_t pos = 0) const;//在當前字符串的pos索引位置開始,,查找第一個不位于子串s的字符,返回找到的位置索引,,-1表示查找不到字符 size_t find_last_of(const char* s, size_t pos = npos) const;//在當前字符串的pos索引位置開始,,查找最后一個位于子串s的字符,返回找到的位置索引,,-1表示查找不到字符 size_tfind_last_not_of (const char* s, size_t pos = npos) const;//在當前字符串的pos索引位置開始,,查找最后一個不位于子串s的字符,返回找到的位置索引,,-1表示查找不到子串 substr(pos,n);//返回字符串從下標pos開始n個字符 char str[] = "I,am,a,student; hello world!"; const char *split = ",; !"; char *p2 = strtok(str,split);
九,、面向?qū)ο蠛皖?/strong>
面向?qū)ο蟾攀?/p>
1、類
類也是一種數(shù)據(jù)類型,。
類的聲明:
成員函數(shù)的定義:類內(nèi),,類外,類外內(nèi)聯(lián)函數(shù)
返回類型 類名:成員函數(shù)名(參數(shù)列表) //內(nèi)聯(lián)函數(shù):類外 inline 返回類型 類名:成員函數(shù)名(參數(shù)列表)
2,、類成員的訪問權(quán)限以及類的封裝
C++中public,、private、protected只能修飾類的成員,,不能修飾類,,C++中的類沒有共有私有之分 類內(nèi)部沒有訪問權(quán)限的限制,都可以互相訪問,。 在C++中用class定義的類中,,其成員的默認存取權(quán)限是private。
3,、對象
類名 對象名(參數(shù)列表);//參數(shù)列表為空時,,()可以不寫 Person p(123, "yar");//在棧上創(chuàng)建對象 Person *pp = new Person(234,"yar");//在堆上創(chuàng)建對象
注:不可以在定義類的同時對其數(shù)據(jù)成員進行初始化,因為類不是一個實體,,不合法但是能編譯運行 對象成員的引用:對象名.數(shù)據(jù)成員名 或者 對象名.成員函數(shù)名(參數(shù)列表)
4,、構(gòu)造函數(shù)
構(gòu)造函數(shù)名必須與類名相同
沒有任何返回值和返回類型
創(chuàng)建對象自動調(diào)用,不需要用戶來調(diào)用,,且只掉用一次
類沒有定義任何構(gòu)造函數(shù),,編譯系統(tǒng)會自動為這個類生成一個默認的無參構(gòu)造函數(shù) 構(gòu)造函數(shù)定義
[類名::]構(gòu)造函數(shù)名(參數(shù)列表)
創(chuàng)建對象
類名 對象名(參數(shù)列表);//參數(shù)列表為空時,()可以不寫
帶默認參數(shù)的構(gòu)造函數(shù)
Person(int = 0,string = "張三"); Person::Person(int a, string s) cout << "age="<<age << endl; cout << "name=" <<name << endl; Person p3(123, "yar");//123 yar
帶參數(shù)初始化表的構(gòu)造函數(shù)
類名::構(gòu)造函數(shù)名(參數(shù)列表):參數(shù)初始化表 參數(shù)名1(初值1),參數(shù)名2(初值2),...,參數(shù)名n(初值n) Person(int = 0,string = "張三"); Person::Person(int a, string s):age(a),name(s) cout << a << " " << s << endl;
構(gòu)造函數(shù)重載:構(gòu)造函數(shù)名字相同,,參數(shù)個數(shù)和參數(shù)類型不一樣,。
拷貝構(gòu)造函數(shù)
Person(Person &p);//聲明拷貝構(gòu)造函數(shù) Person(int = 0,string = "張三"); Person::Person(Person &p)//定義拷貝構(gòu)造函數(shù) cout << "拷貝構(gòu)造函數(shù)" << endl; Person::Person(int a, string s):age(a),name(s) cout << a << " " << s << endl;
5、析構(gòu)函數(shù)
6,、對象指針
對象指針的聲明和使用
對象指針->成員函數(shù)名(參數(shù)列表) Person* pp2 = new Person(234,"yar")
指向?qū)ο蟪蓡T的指針
數(shù)據(jù)成員類型 *指針變量名 = &對象名.數(shù)據(jù)成員名; 函數(shù)類型 (類名::*指針變量名)(參數(shù)列表);
this指針 每個成員函數(shù)都有一個特殊的指針this,,它始終指向當前被調(diào)用的成員函數(shù)操作的對象
Person(int = 0,string = "張三"); Person::Person(int a, string s):age(a),name(s) cout << a << " " << s << endl; cout << "age="<<this->age << endl; cout << "name=" <<this->name << endl;
7、靜態(tài)成員
以關(guān)鍵字static開頭的成員為靜態(tài)成員,,多個類共享,。
- static 成員變量屬于類,不屬于某個具體的對象
- 靜態(tài)成員函數(shù)只能訪問類中靜態(tài)數(shù)據(jù)成員
靜態(tài)數(shù)據(jù)成員
static 數(shù)據(jù)類型 靜態(tài)數(shù)據(jù)成員名; 數(shù)據(jù)類型 類名::靜態(tài)數(shù)據(jù)成員名=初值 類名::靜態(tài)數(shù)據(jù)成員名; 對象名.靜態(tài)數(shù)據(jù)成員名; 對象指針名->靜態(tài)數(shù)據(jù)成員名;
靜態(tài)成員函數(shù)
8,、友元
借助友元(friend),可以使得其他類中得成員函數(shù)以及全局范圍內(nèi)得函數(shù)訪問當前類得private成員,。 友元函數(shù)
友元函數(shù)不是類的成員函數(shù),,所以沒有this指針,必須通過參數(shù)傳遞對象,。 友元函數(shù)中不能直接引用對象成員的名字,,只能通過形參傳遞進來的對象或?qū)ο笾羔榿硪迷搶ο蟮某蓡T。
//1.將非成員函數(shù)聲明為友元函數(shù) Person(int = 0,string = "張三"); friend void show(Person *pper);//將show聲明為友元函數(shù) Person::Person(int a, string s):age(a),name(s) cout << a << " " << s << endl; cout << "age="<< pper->age << endl; cout << "name=" << pper->name << endl; Person *pp = new Person(234,"yar"); //2.將其他類的成員函數(shù)聲明為友元函數(shù) //person中的成員函數(shù)可以訪問MobilePhone中的私有成員變量 Person(int = 0,string = "張三"); void show(MobilePhone *mp); friend void Person::show(MobilePhone *mp); MobilePhone::MobilePhone() Person::Person(int a, string s):age(a),name(s) cout << a << " " << s << endl; void Person::show(MobilePhone *mp) cout << mp->year << "年 " << mp->memory << "G " << mp->name << endl; Person *pp = new Person(234,"yar"); MobilePhone *mp = new MobilePhone;
友元類 當一個類為另一個類的友元時,,稱這個類為友元類,。 友元類的所有成員函數(shù)都是另一個類中的友元成員。 語法形式:friend [class] 友元類名
- 類之間的友元關(guān)系不能傳遞
- 類之間的友元關(guān)系是單向的
- 友元關(guān)系不能被繼承
十,、繼承和派生
1,、繼承
繼承就是再一個已有類的基礎(chǔ)上建立一個新類,已有的類稱基類或父類,,新建立的類稱為派生類和子類,;派生和繼承是一個概念,角度不同而已,,繼承是兒子繼承父親的產(chǎn)業(yè),,派生是父親把產(chǎn)業(yè)傳承給兒子。
一個基類可以派生出多個派生類,,一個派生類可以繼承多個基類
派生類的聲明:
繼承方式:
public-基類的public成員和protected成員的訪問屬性保持不變,,私有成員不可見。 private-基類的public成員和protected成員成為private成員,只能被派生類的成員函數(shù)直接訪問,,私有成員不可見,。 protected-基類的public成員和protected成員成為protected成員,只能被派生類的成員函數(shù)直接訪問,私有成員不可見。
利用using關(guān)鍵字可以改變基類成員再派生類中的訪問權(quán)限,;using只能修改基類中public和protected成員的訪問權(quán)限,。
using Base::aa;//將基類的protected成員變成public using Base::dd;//將基類的protected成員變成public using Base::show;//將基類的public成員變成private Person *p = new Person();
派生類的構(gòu)造函數(shù)和析構(gòu)函數(shù)
- 先執(zhí)行基類的構(gòu)造函數(shù),隨后執(zhí)行派生類的構(gòu)造函數(shù)
- 先執(zhí)行派生類的析構(gòu)函數(shù),,再執(zhí)行基類的析構(gòu)函數(shù),。
- 派生類的構(gòu)造函數(shù):
派生類名(總參數(shù)列表):基類名(基類參數(shù)列表),子對象名1(參數(shù)列表){構(gòu)造函數(shù)體;}
Base::Base(int a, double d) :aa(a), dd(d) cout << "Base Class 構(gòu)造函數(shù)!!!" << endl; cout << "Base Class 析構(gòu)函數(shù)!!!" << endl; Person(int,double,string); Person::Person(int a,double d,string str):Base(a,d),name(str) cout << "Person Class 構(gòu)造函數(shù)!!!" << endl; cout << "Person Class 析構(gòu)函數(shù)!!!" << endl; cout << "創(chuàng)建Person對象..." << endl; Person *p = new Person(1,2,"yar"); cout << "刪除Person對象...." << endl;
2、多繼承
一個派生類同時繼承多個基類的行為,。
多繼承容易讓代碼邏輯復雜,、思路混亂,一直備受爭議,,中小型項目中較少使用,,后來的 Java、C#,、PHP 等干脆取消了多繼承,。
多重繼承派生類聲明的一般形式:
多重繼承派生類的構(gòu)造函數(shù):
二義性問題:多個基類中有同名成員,出現(xiàn)訪問不唯一的問題,。
- 1.
類名::同名成員名; - 2.派生類定義同名成員,,訪問的就是派生類同名成員。
3,、虛基類
c++引入虛基類使得派生類再繼承間接共同基類時只保留一份同名成員,。
虛繼承的目的是讓某個類做出聲明,承諾愿意共享它的基類,。其中,,這個被共享的基類就稱為虛基類(Virtual Base Class)。 派生類的 同名成員 比虛基類的 優(yōu)先級更高 虛基類的聲明:class 派生類名:virtual 繼承方式 基類名
class B: virtual public A class D:public B,public C
如果 B 或 C 其中的一個類定義了a,,也不會有二義性,,派生類的a 比虛基類的a 優(yōu)先級更高。
如果 B 和 C 中都定義了 a,,那么D直接訪問a 將產(chǎn)生二義性問題,。 應用:c++中的iostream , istream ,, ostream,,base_io
4、向上轉(zhuǎn)型
數(shù)據(jù)類型的轉(zhuǎn)換,,編譯器會將小數(shù)部分直接丟掉(不是四舍五入)
只能將將派生類賦值給基類(C++中稱為向上轉(zhuǎn)型): 派生類對象賦值給基類對象,、將派生類指針賦值給基類指針、將派生類引用賦值給基類引用 派生類對象賦值給基類對象,,舍棄派生類新增的成員,;派生類指針賦值給基類指針,,沒有拷貝對象的成員,,也沒有修改對象本身的數(shù)據(jù),,僅僅是改變了指針的指向;派生類引用賦值給基類引用,,和指針的一樣,。、 上轉(zhuǎn)型后通過基類的對象,、指針,、引用只能訪問從基類繼承過去的成員(包括成員變量和成員函數(shù)),不能訪問派生類新增的成員
5,、多態(tài)
不同的對象可以使用同一個函數(shù)名調(diào)用不同內(nèi)容的函數(shù),。
- 靜態(tài)多態(tài)性-在程序編譯時系統(tǒng)就決定調(diào)用哪個函數(shù),比如函數(shù)重載和靜態(tài)多態(tài)性
- 動態(tài)多態(tài)性-在程序運行過程中動態(tài)確定調(diào)用那個函數(shù),,通過虛函數(shù)實現(xiàn)的,。
6、虛函數(shù)
在基類中不執(zhí)行具體的操作,,只為派生類提供統(tǒng)一結(jié)構(gòu)的虛函數(shù),,將其聲明為虛函數(shù)。
實現(xiàn)程序多態(tài)性的一個重要手段,,使用基類對象指針訪問派生類對象的同名函數(shù),。
- 將基類中的函數(shù)聲明為虛函數(shù),派生類中的同名函數(shù)自動為虛函數(shù),。
- 聲明形式:
virtual 函數(shù)類型 函數(shù)名 (參數(shù)列表); - 構(gòu)造函數(shù)不能聲明為虛函數(shù),,析構(gòu)函數(shù)可以聲明為虛函數(shù)。
cout << "A show" << endl; cout << "B show" << endl; pA->show();//B show 如果show方法前沒用virtual聲明為虛函數(shù),,這里會輸出A show
7,、純虛函數(shù)
8、抽象類
十一,、IO流
1,、流類和對象
輸入流-從輸入設備流向內(nèi)存的流。 輸出流-從內(nèi)存流出設備的流,。 內(nèi)存緩沖區(qū)-用來存放流中的數(shù)據(jù),。 輸入輸出流程:鍵盤輸入=》鍵盤緩沖區(qū)=(回車觸發(fā))》程序的輸入緩沖區(qū)=》'>>’提取數(shù)據(jù) 輸出緩沖區(qū)=(緩沖滿或endl)》'<<’送到 顯示器顯示 輸入/輸出流類: iostream:ios ,istream,ostream,iostream fstream:ifstream,ofstream,fstream strstream:istrstream,ostrstream,strstream
- istream 是用于輸入的流類,cin 就是該類的對象,。
- ostream 是用于輸出的流類,,cout 就是該類的對象。
- ifstream 是用于從文件讀取數(shù)據(jù)的類,。
- ofstream 是用于向文件寫入數(shù)據(jù)的類,。
- iostream 是既能用于輸入,又能用于輸出的類。
- fstream 是既能從文件讀取數(shù)據(jù),,又能向文件寫入數(shù)據(jù)的類,。
- istrstream 輸入字符串類
- ostrstream 輸出字符串類
- strstream 輸入輸出字符串流類
2、標準輸入輸出流
C++的輸入/輸出流庫(iostream)中定義了4個標準流對象:cin(標準輸入流-鍵盤),,cout(標準輸出流-屏幕),,cerr(標準錯誤流-屏幕),clog(標準錯誤流-屏幕)
cerr 不使用緩沖區(qū),,直接向顯示器輸出信息,;而輸出到 clog 中的信息會先被存放到緩沖區(qū),緩沖區(qū)滿或者刷新時才輸出到屏幕,。 cout 是 ostream 類的對象,,ostream 類的無參構(gòu)造函數(shù)和復制構(gòu)造函數(shù)都是私有的,所以無法定義 ostream 類的對象,。 使用>>提取數(shù)據(jù)時,,系統(tǒng)會跳過空格,制表符,,換行符等空白字符,。所以一組變量輸入值時,可用這些隔開,。 輸入字符串,,也是跳過空白字符,會在串尾加上字符串結(jié)束標志\0,。
//輸入 22 66.0 兩個數(shù)之間可以用空格,、制表符和回車分隔數(shù)據(jù) cin>>str;//hei ren 字符串中只有hei\0
輸入流中的成員函數(shù)
- get函數(shù):cin.get(),cin.get(ch)(成功返回非0值,,否則返回0),,cin.get(字符數(shù)組(或字符指針),字符個數(shù)n,終止字符)
- getline函數(shù):cin.getline(字符數(shù)組(或字符指針),字符個數(shù)n,終止標志字符)讀取字符知道終止字符或者讀取n-1個字符,,賦值給指定字符數(shù)組(或字符指針)
- cin.peek() 不會跳過輸入流中的空格,、回車符。在輸入流已經(jīng)結(jié)束的情況下,,cin.peek() 返回 EOF,。
- ignore(int n =1, int delim = EOF)
- putback(char c),可以將一個字符插入輸入流的最前面,。
輸出流對象
- 插入endl-輸出所有數(shù)據(jù),,插入換行符,清空緩沖區(qū)
- \n-輸出換行,,不清空緩沖區(qū)
- cout.put(參數(shù)) 輸出單個字符(可以時字符也可以是ASII碼)
格式化輸出 iomanip 中定義的流操作算子:
- *不是算子的一部分,,星號表示在沒有使用任何算子的情況下,,就等效于使用了該算子,例如,,在默認情況下,,整數(shù)是用十進制形式輸出的,等效于使用了 dec 算子
流操作算子使用方法:cout << hex << 12 << "," << 24;//c,18
setiosflags() 算子 setiosflags() 算子實際上是一個庫函數(shù),,它以一些標志作為參數(shù),這些標志可以是在 iostream 頭文件中定義的以下幾種取值,,它們的含義和同名算子一樣,。
多個標志可以用|運算符連接,表示同時設置,。例如:
如果兩個相互矛盾的標志同時被設置,結(jié)果可能就是兩個標志都不起作用,應該用 resetiosflags 清除原先的標志
ostream 類中的成員函數(shù):
setf 和 unsetf 函數(shù)用到的flag,,與 setiosflags 和 resetiosflags 用到的完全相同。
十二,、文件操作
文件-指存儲在外部介質(zhì)上的數(shù)據(jù)集合,,文件按照數(shù)據(jù)的組織形式不一樣,分為兩種:ASCII文件(文本/字符),,二進制文件(內(nèi)部格式/字節(jié))
ASCII文件輸出還是二進制文件,,數(shù)據(jù)形式一樣,對于數(shù)值數(shù)據(jù),,輸出不同
1,、文件類和對象
C++ 標準類庫中有三個類可以用于文件操作,它們統(tǒng)稱為文件流類,。這三個類是:
ifstream:輸入流類,,用于從文件中讀取數(shù)據(jù)。 ofstream:輸出流類,,用于向文件中寫人數(shù)據(jù),。 fstream:輸入/輸出流類,既可用于從文件中讀取數(shù)據(jù),,又可用于 向文件中寫人數(shù)據(jù),。 文件流對象定義:
2、打開文件
open函數(shù):void open(const char* szFileName, int mode);
ios::binary 可以和其他模式標記組合使用
流類的構(gòu)造函數(shù) eg:ifstream::ifstream (const char* szFileName, int mode = ios::in, int);
3,、文件的讀寫
4,、文件指針移動操作
- ifstream 類和 fstream 類有 seekg 成員函數(shù),可以設置文件讀指針的位置,;
- ofstream 類和 fstream 類有 seekp 成員函數(shù),,可以設置文件寫指針的位置。
- ifstream 類和 fstream 類還有 tellg 成員函數(shù),,能夠返回文件讀指針的位置,;
- ofstream 類和 fstream 類還有 tellp 成員函數(shù),,能夠返回文件寫指針的位置。
函數(shù)原型
ostream & seekp (int offset, int mode); istream & seekg (int offset, int mode); //mode有三種:ios::beg-開頭往后offset(>=0)字節(jié) ios::cur-當前往前(<=0)/后(>=0)offset字節(jié) ios::end-末尾往前(<=0)offect字節(jié) //seekg 函數(shù)將文件讀指針定位到文件尾部,,再用 tellg 函數(shù)獲取文件讀指針的位置,,此位置即為文件長度
5、文本文件和二進制文件打開方式的區(qū)別
UNIX/Linux 平臺中,,用文本方式或二進制方式打開文件沒有任何區(qū)別,。 在 UNIX/Linux 平臺中,文本文件以\n(ASCII 碼為 0x0a)作為換行符號,;而在 Windows 平臺中,,文本文件以連在一起的\r\n(\r的 ASCII 碼是 0x0d)作為換行符號。 在 Windows 平臺中,,如果以文本方式打開文件,,當讀取文件時,系統(tǒng)會將文件中所有的\r\n轉(zhuǎn)換成一個字符\n,,如果文件中有連續(xù)的兩個字節(jié)是 0x0d0a,,則系統(tǒng)會丟棄前面的 0x0d 這個字節(jié),只讀入 0x0a,。當寫入文件時,,系統(tǒng)會將\n轉(zhuǎn)換成\r\n寫入。 用二進制方式打開文件總是最保險的,。
十三,、泛型和模板
- 泛型程序設計在實現(xiàn)時不指定具體要操作的數(shù)據(jù)的類型的程序設計方法的一種算法,指的是算法只要實現(xiàn)一遍,,就能適用于多種數(shù)據(jù)類型,,優(yōu)勢在于代碼復用,減少重復代碼的編寫,。
- 模板是泛型的基礎(chǔ),,是創(chuàng)建泛型類或函數(shù)的藍圖或公式
1、函數(shù)模板
函數(shù)模板的一般形式:
template<class T>或template<typename T> 函數(shù)類型 函數(shù)名(參數(shù)列表) template<class T1,class T2,...>//class可以換成typename 函數(shù)類型 函數(shù)名(參數(shù)列表) template<class T> T max(T a, T b) cout <<"max value is "<< max(12,34) << endl;//34 cout << "max value is " << max(12.4, 13.6) << endl;//13.6 cout << "max value is " << max(12.4, 13) << endl;//error 沒有與參數(shù)列表匹配的 函數(shù)模板 "max" 實例參數(shù)類型為:(double, int)
2,、類模板
聲明了類模板,,就可以將類型參數(shù)用于類的成員函數(shù)和成員變量了。換句話說,,原來使用 int,、float、char 等內(nèi)置類型的地方,,都可以用類型參數(shù)來代替,。 類模板的一般形式:
當類中的成員函數(shù)在類的聲明之外定義時,它必須定義為函數(shù)模板,,帶上模板頭,,定義形式如下:
3,、模板的使用
4、typename 和 class 的區(qū)別
在模板引入 c++ 后,,采用class來定義模板參數(shù)類型,,后來為了避免 class 在聲明類和模板的使用可能給人帶來混淆,所以引入了 typename 這個關(guān)鍵字,。
模板定義語法中關(guān)鍵字 class 與 typename 的作用完全一樣,。 不同的是typename 還有另外一個作用為:使用嵌套依賴類型(nested depended name)
LengthType getLength() const void setLength(LengthType length) //告訴 c++ 編譯器,typename 后面的字符串為一個類型名稱,,而不是成員函數(shù)或者成員變量 typedef typename T::LengthType LengthType; // LengthType length = myclass.getLength(); cout << "length = " <<length<< endl; MyMethod(my);//length = 666
十四,、命名空間和異常處理
1、命名空間
命名空間實際上是由用戶自己命名的一塊內(nèi)存區(qū)域,,用戶可以根據(jù)需要指定一個有名字的空間區(qū)域,,每個命名空間都有一個作用域,,將一些全局實體放在該命名空間中,就與其他全局實體分割開來,。 命名空間定義的一般形式:
命名空間成員的引用:命名空間名::命名空間成員名 使用命名空間別名:namespace 別名 = 命名空間名 使用using聲明命名空間成員的格式:using 命名空間名::命名空間成員名; 使用using聲明命名空間的全部成員:using namespace 命名空間名;
using聲明后,,在using語句所在的作用域中使用該命名空間成員時,,不必再用命名空間名加以限定。 標準C++庫的所有標識符(包括函數(shù),、類,、對象和類模板)都是在一個名為std的命名空間中定義的,。 無名的命名空間,只在本文件的作用域內(nèi)有效,。
2,、異常處理
十五,、STL
C++標準模板庫(Standard Template Library,STL)是泛型程序設計最成功的實例。STL是一些常用數(shù)據(jù)結(jié)構(gòu)和算法的模板的集合,,由Alex Stepanov主持開發(fā),于1998年被加入C++標準,。
C++ 標準模板庫的核心包括三大組件:容器,,算法,,迭代器
1、容器
順序容器:可變長動態(tài)數(shù)組Vector,、雙端隊列deque、雙向鏈表list 關(guān)聯(lián)容器:set,、multliset,、map、multimap
關(guān)聯(lián)容器內(nèi)的元素是排序的,所以查找時具有非常好的性能,。 容器適配起:棧stack,、隊列queu,、優(yōu)先隊列priority_queue 所有容器具有的函數(shù):
順序容器和關(guān)聯(lián)容器函數(shù):
順序容器獨有的函數(shù):
2,、迭代器
迭代器是一種檢查容器內(nèi)元素并遍歷元素的數(shù)據(jù)類型。C++更趨向于使用迭代器而不是下標操作,,因為標準庫為每一種標準容器(如vector)定義了一種迭代器類型,,而只用少數(shù)容器(如vector)支持下標操作訪問容器元素。按照定義方式分為以下四種,。
- 正向迭代器:容器類名::iterator 迭代器名;
- 常量正向迭代器:容器類名::const_iterator 迭代器名;
- 反向迭代器:容器類名::reverse_iterator 迭代器名;
- 常量反向迭代器:容器類名::const_reverse_iterator 迭代器名
3、算法
STL 提供能在各種容器中通用的算法(大約有70種),如插入,、刪除,、查找,、排序等,。算法就是函數(shù)模板。算法通過迭代器來操縱容器中的元素。 STL 中的大部分常用算法都在頭文件 algorithm 中定義。此外,,頭文件 numeric 中也有一些算法,。 許多算法操作的是容器上的一個區(qū)間(也可以是整個容器),因此需要兩個參數(shù),,一個是區(qū)間起點元素的迭代器,,另一個是區(qū)間終點元素的后面一個元素的迭代器。 會改變其所作用的容器,。例如:
- copy:將一個容器的內(nèi)容復制到另一個容器,。
- remove:在容器中刪除一個元素。
- random_shuffle:隨機打亂容器中的元素,。
- fill:用某個值填充容器,。
不會改變其所作用的容器。例如:
- find:在容器中查找元素,。
- count_if:統(tǒng)計容器中符合某種條件的元素的個數(shù),。
v.push_back(4); //1,2,3,4 p = find(v.begin(), v.end(), 3); //在v中查找3 若找不到,find返回 v.end() cout << "1) " << *p << endl; //找到了 p = find(v.begin(), v.end(), 9); cout << "not found " << endl; //沒找到 p = find(v.begin() + 1, v.end() - 1, 4); //在2,3 這兩個元素中查找4 cout << "2) " << *p << endl; //沒找到,指向下一個元素4 int arr[10] = { 10,20,30,40 }; int * pp = find(arr, arr + 4, 20); cout << "not found" << endl; cout << "3) " << *pp << endl;
|