當(dāng)前位置:首頁(yè) > 嵌入式培訓(xùn) > 嵌入式學(xué)習(xí) > 學(xué)習(xí)筆記 > C++學(xué)習(xí)總結(jié),學(xué)霸課堂筆記
Day1
名字空間:用來限制作用域(重名問題)
Using namespace std; 全局的聲明,只有一次聲明之后使用的std中的東西就可以直接用。
::std 全局
Using myspace ::demo 使用myspace中的demo。
換行: endl \n
cin >> ival >> ch
cout << ival << ch << endl
————————————
Oop思想:面向?qū)ο蟮乃枷?/p>
屬性+行為=對(duì)象
(記憶 體會(huì) 實(shí)踐 理解 發(fā)揮)
類的聲明定義:(聲明與定義分開)
Class 聲明類
Class Demo(類名)
成員的性質(zhì)(public 公共 ———— private 私有(一般數(shù)據(jù)私有) ———— protected 保護(hù))
——————————
構(gòu)造函數(shù):不需要用戶來調(diào)用它也不能調(diào)用,而是在建立對(duì)象時(shí)自動(dòng)執(zhí)行
構(gòu)造函數(shù)的名字必須與類名同名,而不能由用戶任意命名,以便以其系統(tǒng)能識(shí)別它并把它作為構(gòu)造函數(shù)處理
構(gòu)造函數(shù)的功能是由用戶定義的,用戶根據(jù)初始化的要求設(shè)計(jì)函數(shù)體和函數(shù)參數(shù)
如果用戶不設(shè)計(jì),則編譯器自動(dòng)生成一個(gè)默認(rèn)構(gòu)造函數(shù)
無返回值
普通默認(rèn)構(gòu)造
拷貝構(gòu)造 用已有的構(gòu)造新的
深拷貝和淺拷貝 默認(rèn)的拷貝函數(shù)為淺拷貝,當(dāng)有指針類成員時(shí)一定要自己做拷貝函數(shù)做深拷貝(使得數(shù)據(jù)區(qū)域獨(dú)立 不光是拷貝值)
Demo(const Demo & )
限制構(gòu)造 類中的成員屬于私有或者保護(hù) 不允許構(gòu)造
——————————
析構(gòu)函數(shù): 對(duì)象銷毀時(shí)自動(dòng)調(diào)用(對(duì)于同一生命周期的成員 先構(gòu)造的后析構(gòu) )
不能重載
只能用~Demo()
全局對(duì)象,進(jìn)程結(jié)束時(shí)對(duì)象自動(dòng)銷毀,析構(gòu)自動(dòng)調(diào)用
局部對(duì)象,func()調(diào)用構(gòu)造,func結(jié)束析構(gòu)
靜態(tài)局部對(duì)象,進(jìn)程生命期,func第一次調(diào)用構(gòu)造,進(jìn)程結(jié)束析構(gòu)
堆對(duì)象,運(yùn)行時(shí)候構(gòu)造,必須是delete對(duì)象才會(huì)銷毀,且自動(dòng)析構(gòu),如果不delete就不析構(gòu)
————————————
This 指針:
指向?qū)ο笞约?/p>
Private 成員 只能在內(nèi)部使用
Const 成員 不可修改
————————————
分析構(gòu)造和析構(gòu)的次數(shù)
——————————————————————————————————————————————————
Day3
Static :
Static 成員 (靜態(tài)成員是一種特殊成員)
不屬于任何類對(duì)象(有沒有對(duì)象都靜態(tài)成員就已經(jīng)存在,且是進(jìn)程生命期)
作用域在類域
靜態(tài)的,唯一的
用于限制作用域
————————————
Const :
Const 成員函數(shù) 在函數(shù)后面加const,表示該成員函數(shù)不能修改類對(duì)象(在這個(gè)函數(shù)內(nèi)不能存在修改類對(duì)象的任何操作)
只要類方法不修改對(duì)象就應(yīng)該聲明為const
Const 對(duì)象 const Demo obj; //只讀對(duì)象,不能被修改(obj 被定義為Demo類的只讀對(duì)象不可以被修改)
只要調(diào)用成員函數(shù),就存在修改對(duì)象的風(fēng)險(xiǎn),所以不能再調(diào)用成員函數(shù)。語法上不允許調(diào)用普通成員函數(shù)
Const 成員變量 const int x
只讀成員變量,那么必須使用初始化列表進(jìn)行初始化
Demo::Demo(int a) : x(a) //初始化列表
只要調(diào)用x就會(huì)檢查會(huì)不會(huì)修改,x被const修飾所以不能被修改。
————————————
友元:(打破封裝可訪問類中的private protected對(duì)象)
友元的聲明可以放在類的私有部分,也可以放在公有部分,它們是沒有區(qū)別的
慎用友元,存在危險(xiǎn)性。
友元函數(shù) 一個(gè)函數(shù)可以是多個(gè)類的友元函數(shù),只需要在各個(gè)類中分別聲明。調(diào)用與一般函數(shù)的調(diào)用方法和原理一致
友元類 友元關(guān)系不能被繼承,是單向的,不具有傳遞性
聲明友元類時(shí)需要前項(xiàng)聲明(前項(xiàng)聲明可以不列出具體內(nèi)容)
友元成員函數(shù) 存在遞歸可能 所以最好聲明定義引用分開編寫。
前項(xiàng)聲明不足以完全說清楚所以分開編寫。
————————————————————————————————————————————————————————————————
Day4
運(yùn)算符重載:(重載——函數(shù)同名,參數(shù)不同,行為相似)
運(yùn)算符重載——特殊的一種重載 (加 operator)
友元運(yùn)算符重載 與函數(shù)對(duì)比,功能相同
friend const int* getaddr(const Demo &);
friend Demo& addeq(Demo &, const Demo &);
函數(shù)實(shí)現(xiàn)功能不直觀不容易被理解
friend const int* operator& (const Demo &);
friend Demo& operator += (Demo &, const Demo &);
運(yùn)算符重載實(shí)現(xiàn)功能直觀便于理解
friend Demo& operator ++ (Demo &); 前++
friend Demo& operator ++ (Demo &,int);后++
——————————
成員函數(shù)運(yùn)算符重載 成員函數(shù)在類中 屬于類 可以使用this 指針?biāo)猿蓡T函數(shù)的運(yùn)算符重載在傳參數(shù)時(shí) 參數(shù)個(gè)數(shù)和友元運(yùn)算符重載不同。
bool operator !=(Integer &)
bool是判斷返回值(對(duì)或者錯(cuò))
【】通過數(shù)組名[]訪問數(shù)組成員,即得到一個(gè)對(duì)象
通過數(shù)組名[]訪問數(shù)組成員,即得到一個(gè)對(duì)象,
對(duì)象有一個(gè)運(yùn)算符[]得到對(duì)象管理的整型數(shù)組的一個(gè)整型
arr[0]:IntArray對(duì)象
arr[0][0]:是一個(gè)整型
————————————
注意事項(xiàng) 除關(guān)系運(yùn)算符“.”、作用域運(yùn)算符“::”、sizeof運(yùn)算符和三目運(yùn)算符“:?”外,C++中的所有運(yùn)算符都可以重載(其中“=”和“&”不必用戶重載)
重載運(yùn)算符限制限制在C++語言中已經(jīng)有的運(yùn)算范圍內(nèi)的允許重載的運(yùn)算符之中,不能創(chuàng)建新的運(yùn)算符。
運(yùn)算符重載的實(shí)質(zhì)就是函數(shù)重載,遵循函數(shù)重載的選擇原則
重載之后的運(yùn)算符不能改變運(yùn)算符的優(yōu)先級(jí)和結(jié)合性,也不能改變運(yùn)算符操作數(shù)的個(gè)數(shù)及語法結(jié)構(gòu)
運(yùn)算符重載不能改變?cè)撨\(yùn)算符用于內(nèi)部類型的對(duì)象的含義
運(yùn)算符重載是針對(duì)新類型數(shù)據(jù)的實(shí)際需要對(duì)原有運(yùn)算符進(jìn)行的適當(dāng)?shù)母脑欤剌d的功能應(yīng)當(dāng)與原有功能相類似,避免沒有目的地使用重載運(yùn)算符
重載運(yùn)算符的函數(shù)不能有默認(rèn)參數(shù),否則就改變了運(yùn)算符的參數(shù)個(gè)數(shù)
重載的運(yùn)算符只能是用戶自定義類型,否則就不是重載而是改變了現(xiàn)有的C++標(biāo)準(zhǔn)數(shù)據(jù)類型的運(yùn)算符的規(guī)則
運(yùn)算符重載可以通過成員函數(shù)的形式,也可以通過友元函數(shù)的形式,和非成員的普通函數(shù)
————————————————————————————————————————————————————
Day 5
模板:模板是對(duì)一種對(duì)類型進(jìn)行參數(shù)化的工具。
模板的聲明或者定義只能在全局,命名空間或者類范圍內(nèi)進(jìn)行。即不能在局部范圍,函數(shù)內(nèi)進(jìn)行。
函數(shù)模板 參數(shù)類型不一樣的但是功能及函數(shù)名一樣的函數(shù)
函數(shù)模板的聲明定義語法上差異不大,就像普通函數(shù)一樣使用
template
T add(T x, T y);
template
C add(C x, C y)
{
return x+y;
}
類模板 成員屬性的類型和成員函數(shù)的類不一樣但是成員屬性及函數(shù)一樣的類
template
class Demo{
public:
Demo(T1 a, T2 b);
void setx(T1 a);
static void sety(Demo &, T2 val);
T1 getx() const;
T2 gety() const;
private:
static T1 x;
T2 y;
};
友元函數(shù)模板
如果一個(gè)類是模板類,又要實(shí)現(xiàn)運(yùn)算符重載,就是一個(gè)友元函數(shù)模板;
實(shí)質(zhì)是類模板和函數(shù)模板的綜合運(yùn)用
template
class Demo{
public:
Demo(const int val);
public:
T getval() const;
void setval(const int val);
template
friend Demo
private:
T ival;
};
非類型模板參數(shù)
template
class Array{
public:
Array();
Array(const Array &);
~Array();
public:
T& at(const int id=0) const;
T& operator[](const int id)const;
private:
T* const buffer;
};
T:模板類型參數(shù);len:模板非類型參數(shù);T、len都可以有默認(rèn)值
————————————————————————————————————————————
Day 6
繼承: 就是在一個(gè)已存在的類的基礎(chǔ)上建立一個(gè)新的類。已存在的類(學(xué)生)稱為“基類”(或父類),新建立的類(小學(xué)生)稱為“派生類”(或子類)
1.派生類繼承了基類的所有數(shù)據(jù)成員和成員函數(shù)(private雖然也繼承了,但是無法直接訪問),并可以對(duì)成員作必要的增加和調(diào)整。
2.一個(gè)基類可以派生出多個(gè)派生類,每一個(gè)派生類又可以作為基類再派生出新的派生類,因此基類和派生類是相對(duì)而言的。
3.派生類是基類的具體化,而基類則是派生類的抽象。
繼承權(quán)限 :
1.public:公有繼承。
a.公有成員變成派生類的公有成員。 b.保護(hù)成員變成派生類的保護(hù)成員。 c.私有成員:只能通過基類接口訪問。
2.protected:保護(hù)繼承。
a.公有成員,保護(hù)成員都變成派生類的保護(hù)成員 b.私有成員:只能通過基類接口訪問。
3.private:私有繼承。
a.公有成員,保護(hù)成員都變成派生類的私有成員 b.私有成員:只能通過基類接口訪問。
子類的構(gòu)造析構(gòu):
順序——構(gòu)造:先基類、再派生;析構(gòu):先派生、再基類
(因?yàn)榕缮惖臉?gòu)造和析構(gòu) 可能會(huì)用到基累的成員,所以派生的構(gòu)造在基類后,派生的析構(gòu)在基類前)
Is-a
什么是a (香蕉是水果 水果為a是基類 )
Has-a
什么有a
(思想要理解 咋實(shí)踐中深入)
多重繼承:
class <派生類名> : <繼承方式1> <基類名1>,<繼承方式2><基類名2>……
使用需要注意 容易引起歧義
————————————————————————————————————————————————————————————————
Day 7
多態(tài):多種狀態(tài)(一個(gè)接口, 多種方法) 程序運(yùn)行時(shí)才決定調(diào)用的函數(shù),是面向?qū)ο缶幊填I(lǐng)域的核心概念。
多態(tài)是將接口和實(shí)現(xiàn)進(jìn)行分離,(實(shí)現(xiàn)以共同的方法,但因?yàn)閭(gè)體差異,而采用不同的策略)
多態(tài)的應(yīng)用場(chǎng)景
如果基類實(shí)現(xiàn)不是我們想要的方法,那么在子類派生時(shí),重寫一個(gè)新的版本
這樣其他成員函數(shù)不可以直接復(fù)用,這樣的情況就需要虛函數(shù),即多態(tài)
虛函數(shù) 子類和基類有相同的方法,但是行為卻有所不同(多態(tài))
(is-a 的關(guān)系不是多態(tài),函數(shù)重載(函數(shù)行為相似)也不是多態(tài))
用virtual修飾成員函數(shù)(虛函數(shù))
1. 非類的成員函數(shù)不能定義為虛函數(shù)
2. 類的靜態(tài)成員函數(shù)不能定義為虛函數(shù)
3. 構(gòu)造函數(shù)不能定義為虛函數(shù),(析構(gòu)可以定義為虛函數(shù))
4. 只需要在聲明函數(shù)的類體中使用關(guān)鍵字virtual將函數(shù)聲明為虛函數(shù),而定義函數(shù)時(shí)不需要再使用關(guān)鍵字virtual
5. 當(dāng)將基類中的某一成員函數(shù)聲明為函數(shù)后,派生類中的同名函數(shù)(函數(shù)名相同,參數(shù)列表完全一致,返回值類型相關(guān))自動(dòng)成為虛函數(shù)
抽象類 隱藏類的其他成員的方法。
1. 含有純虛函數(shù)的類就是抽象類
2. 抽象類沒有完整的信息,只能是派生的基類
3. 抽象類不能有實(shí)例,不能有靜態(tài)成員
4. 派生類應(yīng)該實(shí)現(xiàn)抽象類的所有方法
5. 抽象類不能定義對(duì)象,因?yàn)槠浼兲摵瘮?shù)只有聲明沒有定義
6. 抽象類被使用只能派生,且只有有子類對(duì)象
虛析構(gòu) 由于指針指向的對(duì)象是基類類型,所以delete銷毀對(duì)象的時(shí)候,并不會(huì)調(diào)用派生類的析構(gòu)函數(shù),這樣級(jí)造成了對(duì)象銷毀不完整。
工程原則:只要該類要被繼承,則析構(gòu)必須是虛函數(shù)
構(gòu)造函數(shù)不能為虛,析構(gòu)函數(shù)一定為虛
virtual ~Base() const = 0 純虛析構(gòu)函數(shù)
虛繼承 解決從不同途徑繼承來的同名的數(shù)據(jù)成員在內(nèi)存中有不同的拷貝造成數(shù)據(jù)不一致的問題,將共同基類設(shè)置為虛基類。
從不同的路徑繼承過來的同名數(shù)據(jù)成員在內(nèi)存中就只有一個(gè)拷貝,同一個(gè)函數(shù)名也只有一個(gè)映射。
typeid(this).name() 類名
聯(lián)編(鏈接) 將模板或者函數(shù)合并在一起生成可執(zhí)行代碼的處理過程。
靜態(tài)聯(lián)編(靜態(tài)鏈接) 在編譯階段就將函數(shù)實(shí)現(xiàn)和函數(shù)調(diào)用聯(lián)起來(早綁定)
動(dòng)態(tài)聯(lián)編(動(dòng)態(tài)鏈接) 在程序執(zhí)行的時(shí)候才將函數(shù)實(shí)現(xiàn)和函數(shù)調(diào)用關(guān)聯(lián)(晚綁定)——引入一個(gè)虛函數(shù)表實(shí)現(xiàn)
C++中一般情況下的聯(lián)編指靜態(tài)聯(lián)編,一旦涉及到多態(tài)和虛擬函數(shù)就必須使用動(dòng)態(tài)聯(lián)編
重載只是一種語言特性,編譯器根據(jù)函數(shù)不同的參數(shù)表,把同名函數(shù)區(qū)分開來屬于靜態(tài)聯(lián)編,與多態(tài)無關(guān)。
—————————————————————————————————————————————————————————
Day 8
異常: 讓一個(gè)函數(shù)在發(fā)現(xiàn)了自己無法處理的錯(cuò)誤時(shí)拋出(throw)一個(gè)異常,然后他的(直接或間接)調(diào)用者能夠處理這個(gè)問題。
異常處理機(jī)制是一種比較有效的處理系統(tǒng)運(yùn)行時(shí)錯(cuò)誤的方法。
在執(zhí)行程序發(fā)生異常時(shí),可以不在本函數(shù)中處理,而是拋出一個(gè)錯(cuò)誤信息,把它傳遞給上一級(jí)的函數(shù)來解決,上一級(jí)解決不了再傳遞給上一級(jí),一直直到最高一層還無法處理的話,運(yùn)行系統(tǒng)會(huì)自動(dòng)調(diào)用系統(tǒng)函數(shù)terminate,由他調(diào)用abort終止程序。
異常處理——try(檢查)——》throw(拋出)——》catch(捕獲)
自定義異常 設(shè)計(jì)程序時(shí)會(huì)自定義很多錯(cuò)誤,這些錯(cuò)誤在標(biāo)準(zhǔn)錯(cuò)誤里是沒有的,所以我們往往需要自定義很多異常類。
自定義異?梢詮臉(biāo)準(zhǔn)異常exception類派生出來 也可以完全自定義一個(gè)異常類。
在定義的異常函數(shù)后必須加上空異常的關(guān)鍵字——因?yàn)楫惓:瘮?shù)自身需要嚴(yán)格定義不允許異常函數(shù)有異常報(bào)出。(通用 throw() 空異常 高版本用 nothrow關(guān)鍵字)
轉(zhuǎn)換函數(shù):
Int val = 0;
Char ch = ‘a’;
Int main (int argc, char *argv[])
{
Val = ch; //隱式轉(zhuǎn)換
Ch = char(val) // 顯式轉(zhuǎn)換
}
轉(zhuǎn)換函數(shù)的實(shí)質(zhì)為運(yùn)算符重載,只是重載的運(yùn)算符不是內(nèi)置的運(yùn)算符而是類
Operator 類型名()
{
實(shí)現(xiàn)轉(zhuǎn)換的語句
}
規(guī)則——轉(zhuǎn)換函數(shù)只能是成員函數(shù),無返回值,空參數(shù)
不能定義為void的轉(zhuǎn)換,也不允許轉(zhuǎn)換成數(shù)組或者函數(shù)類型
轉(zhuǎn)換常定義為const形式,(轉(zhuǎn)換函數(shù)并不改變數(shù)據(jù)成員的值)
Explicit關(guān)鍵字—— 修飾類的構(gòu)造函數(shù),被修飾的構(gòu)造函數(shù)的類,不能發(fā)生相應(yīng)的隱式類型轉(zhuǎn)換
給單參數(shù)的構(gòu)造函數(shù)使用explicit關(guān)鍵字,阻止可能產(chǎn)生的隱式轉(zhuǎn)換:由成員變量類型轉(zhuǎn)換為類類型