C++知識點整理總結:
目錄
一. C++(I)重點知識:
二. C++(II)重點知識:
C++書寫標准:
- 數據放在private中
- 參數盡量用引用來傳,需不需要const,看情況。
- 返回值盡量用引用來傳
- 在類的本體中,函數應該加const的要加。
- 構造函數中的參數初始化列表要盡量用。
一.C++(I)重點知識:
主要介紹了兩種class類型:1)class中不帶指針成員 2)class中包含指針成員
*包含頭文件的兩種方法#include<>和#include””;
如果是自己寫的頭文件,使用#include””包含, 如果包含的是C++標准庫,使用#include<>來包含。
頭文件中使用防衛式聲明:
建議:為了不必要的麻煩,最好在每個頭文件上加上這樣的防衛式聲明。即使現在你只有一個cpp使用該頭文件,萬一之后再有別的cpp使用該頭文件嘞。
PS:防衛式聲明一般這樣寫:__(2個下划線,不是1個)+頭文件名的大寫(不包括.h)+__(2個下划線,不是1個),例如頭文件為head.h時,就使用__HEAD__,這是為了防止重復。
目錄
一. C++(I)重點知識:
1) class中不帶指針成員
2) class中包含指針成員
1. Prototype設計模式:
2. 委托+繼承關系下的Composite設計模式應用於文件系統開發的原理
3. 委托+繼承關系下的observer設計模式的應用和原理
4. 繼承+復合關系下的構造與析構函數調用
5. 虛函數和TemplateMethod模式的原理和應用重點
6.復合關系和Adapter模式以及復合關系下的構造和析構函數的講解
二. C++(II)重點知識:
1) class中不帶指針成員
- 關於inline的用法:
Inline用於函數的聲明,函數可以被聲明為inline類型及內聯類型, inline函數提高運行效率(inline只是對編譯器的一種建議,簡單函數會被inline,復雜函數不一定會被inline),建議將函數inline.
在class內完成定義的函數,編譯器會自動對其進行inline 嘗試。
在class外完成定義的函數,可以使用inline關鍵字對其進行inline嘗試。
2.關於友元函數的使用:
面向對象三大特性:封裝,繼承,多態。友元函數可以說是在保持封裝性的情況下,提供了其他對象對另一個對象的操作方式(兩個對象可以屬於同一class,也可以不屬於同一個class);同一class的不同對象之間是友元關系。
3.常量const的使用:
Const 修飾對象,若函數體內,不會對傳入對象進行修改,則函數形參前加const,表示此對象在函數運行過程中不會被改變。
Const修飾函數, 即在函數名()之后加const修飾,可以保證函數在之后的運行過程中可以正確運行。可以使用以下例子來說明:
函數名( )之后加const,意味函數體內不會對成員數據進行任何更改操作。
之后無論是使用complex c1(2,1) 還是 const complex c1(2,1)來創建對象都可以;但是,如果不加const,使用 const complex c1(2,1)創建對象后,cout<<c1.real( )會報錯。
4.關於構造函數的使用:
合理運用初始化列表可以有效提高運行效率。
構造函數的執行過程:先執行初始化列表,后執行函數體中的內容。
構造函數重載注意事項:
5.關於運算符重載:
1) return by value 還是 return by referrence??
若在函數內部沒有創建臨時對象,則盡量使用引用類型對返回值進行接收; 若在函數內部創建臨時,則使用value對返回值進行接收.
使用reference接收的好處:
2) 臨時對象:
再一個函數中,通過調用構造函數生成臨時的一個對象,用來存儲新生成的數據,當函數執行結束后,臨時對象將會被編譯器清除,可以通過返回value的方式,將臨時對象中的數據返回。
3) 運算符重載(+,+=,<<)
重載<<, ostream& operator<<( ostream& os,const String str ) ,需要將重載函數寫成全局函數。
2) class中包含指針成員
1.array New一定要搭配array Delete 使用:
例如:
如圖: new String[3]意味創建了包含3個string類型對象的數組,在創建過程中會調用3次String類型的構造函數; 如果使用delelte p來釋放p指針,則只會調用一次析構函數,釋放p所指向的數組空間的第一個string對象, 但是數組空間中其余2個string類型對象中包含指針數據,指針數據所指向的內存空間並不會被釋放掉,造成內存泄漏; 因此必須使用delelte [] p。array New一定要搭配array Delete使用。
2.namespace的使用:
3.stack和heap以及new和delete的使用和原理
- static的使用:
將class中的數據成員設置為static類型,或者將函數成員設置為static類型。設置為static的數據成員和函數成員,在內存中單獨存在,static函數成員只能處理static數據成員,static函數中不包含this指針。
調用static函數的方式:
(1)通過object調用
(2)通過class name調用
1.單例模式:(singleton)
單例模式:確保一個類只有一個實例,並提供一個全局訪問點。
例子:構造函數放在private域中
在此例子中只需要一個A的對象,可以使用單例模式來完成。
此例子中:
A的構造函數寫在了private中,成員函數getinstance()用來創建一個A的靜態對象a,並返回a對象的引用。
應用:單例模式可以用來做初始化數據庫的連接操作,線程池,緩存,日志對象,顯卡等設備的驅動程序。
經典的單例模式實現(java)(延遲實例化):
Public class Singleton{
Private static Singleton uniqueInstance;
//這里是其他的有用實例化變量
Private Singleton( ) { } //私有的構造函數
Public static Singleton getInstance( )
{
If(uniqueInstance == null)
{
uniqueInstance= new Singleton( );
}
Return uniqueInstance;
}
//這里是其他的有用方法
}
以上情況注意***在使用單例模式時,需要考慮多線程並發導致生成多個實例的情況。
處理多線程的方法:
1.將getInstance()變成同步(synchronized)方法, 若此段程序使用頻繁,此方法會造成程序效率的大幅下降。
經典的單例模式實現(java)(延遲實例化):
Public class Singleton{
Private static Singleton uniqueInstance;
//這里是其他的有用實例化變量
Private Singleton( ) { } //私有的構造函數
Public static synchronized Singleton getInstance( )
{
If(uniqueInstance == null)
{
uniqueInstance= new Singleton( );
}
return uniqueInstance;
}
//這里是其他的有用方法
}
2.使用”雙重檢查加鎖”,在getInstance()中減少使用同步。保證程序的性能。(最佳方法)
Public class Singleton{
Private Volatile static Singleton uniqueInstance;
//這里是其他的有用實例化變量
Private Singleton( ) { } //私有的構造函數
Public static Singleton getInstance( )
{
If(uniqueInstance == null)
{
synchronized (Singleton.class)
{
If(uniqueInstance == null)
{
uniqueInstance= new Singleton( );
}
}
}
return uniqueInstance;
}
//這里是其他的有用方法
}
使用”急切”創建實例,而不是使用延遲實例化的做法
經典的單例模式實現(java)(急切實例化):
Public class Singleton{
Private static Singleton uniqueInstance = new Singleton( );
//這里是其他的有用實例化變量
Private Singleton( ) { } //私有的構造函數
Public static Singleton getInstance( )
{
return uniqueInstance;
}
//這里是其他的有用方法
}
- cout函數的原理說明:
- 模板和函數模板:
- 淺拷貝和深拷貝:
class中包含指針數據成員,需要定義一下三種函數:
BIG Three函數:1.拷貝構造函數 2.拷貝賦值函數 3.析構函數
淺拷貝:
c++中,提供的對象之間的賦值是淺拷貝,例如:a=b; 將對象b賦值給對象a, 只是將a和b對象中的指針指向同一地址,這樣會造成內存泄露;同時也會帶來不確定性的危險,例如:在后續操作中,改變a或b中的某一指針所指地址中的數據,相當於a和b同時改變。
深拷貝:
通過拷貝構造函數不改變a和b對象中指針的地址,而將所指地址中的數據改為相同。
深拷貝兩種方法:
1.拷貝構造函數:利用構造函數來進行對象的拷貝,例如:
String s1("Hello");
String s2(s1); //調用所屬class的拷貝構造函數
2.拷貝賦值函數:利用運算符重載來進行對象的拷貝(賦值), 例如:
String s1("Hello");
String s2;
s2 = s1; // 調用class中operator成員函數
3.析構函數:在對象的生命周期結束時,被調用,用來將對象中的指針所指地址進行釋放。
9.參數傳遞:pass by value vs pass by reference(to const)
1.使用value傳遞,可能因為數據的大小影響運行效率。例如:char數據是1個字節,指針是4個字節,”引用”本質上是指針的封裝,但是速度比指針更快。
2.使用引用傳遞,速度更快,並且和指針傳遞效果一樣,在函數內對可以對引用的數據進行修改。
3.上圖中,complex& operator += (const complex&); 其中const表明:通過引用傳遞到函數體內的數據不能在函數體內進行修改。
返回值類型盡量使用引用。
面向對象編程重中之重(繼承、復合、委托)
復合關系:及在一個類的數據成員中包含包含其他類的對象。
繼承關系:及子類繼承父類
委托關系:及在一個類的數據成員中包含包含其他類的指針。
- Prototype設計模式:
- 委托+繼承關系下的Composite設計模式應用於文件系統開發的原理
- 委托+繼承關系下的observer設計模式的應用和原理
- 繼承+復合關系下的構造與析構函數調用
- 虛函數和TemplateMethod模式的原理和應用重點
6.復合關系和Adapter模式以及復合關系下的構造和析構函數的講解
復合關系下,構造函數是先調用內部復合的構造函數,然后再執行自己的構造函數。析構函數是先執行自己的析構函數,再執行內部復合的析構函數。
二.C++(II)重點知識:
- 轉換函數conversion function
- Pointer-like-class智能指針
Pointer-like-class智能指針: 就是像指針的class, 該類所創建的對象,擁有普通指針所擁有的功能,此外還可以根據自己的需要對其進行擴展。
- pointer-like-class智能指針-迭代器
- function-like-class仿函數
- class template 和 function template 和 menber template
- 模板特化和模板偏特化
- 模板模板參數
- reference的本質原理理解(重點)
9.復合繼承關系下的構造和析構
復合關系下,構造函數是先調用內部復合的構造函數,然后再執行自己的構造函數。析構函數是先執行自己的析構函數,再執行內部復合的析構函數。
10.多態與虛函數與虛機制與虛指針的本質理解和關系
如果一個類中包含虛函數,則再內存分配中,會為該類的對象分配一個虛指針vptr,不論class中有多少個虛函數,對象中都只有一個虛指針; 虛指針指向虛表vtbl虛表中存有對象所包含虛函數的地址; 虛機制:就是對象在調用虛函數的過程中,通過虛指針找到虛表,通過虛表中虛函數的地址找到相應的虛函數,進行調用的過程。 多態是靠虛機制來進行表現。
- 關於this指針的理解:
當對象調用所屬類的函數成員時,會隱式的將對象的地址傳入函數中,this就是指向這個對象的指針。
- 關於動態綁定的理解:
動態綁定是與虛機制有關的,
- 關於new, delete, operatorNew和operatorDelete的重載(難)可用來做內存池
裝飾者模式(組合composition+委托delegation):
適用於的情景: 利用繼承無法完全解決問題,類數量爆炸、設計死板,以及基類加入的新功能並不適用於所有的子類。
目標是:允許類容易擴展,在不修改現有代碼的情況下,就可以搭配新的行為,及(對擴展開放,對修改關閉)
注意:在選擇需要被擴展的代碼部分時要小心。每個地方都采用開放-關閉原則,是一種浪費,也沒必要,還會導致代碼變得復雜且難以理解。
觀察者模式