[toc]
C++面向?qū)ο蟾呒夐_發(fā)(全集)
https://www.bilibili.com/video/BV1K4411974P?p=1
C++編程簡介
C++ 演化
書籍推薦:
effective C++
stl源碼剖析
C vs C++ 關(guān)于數(shù)據(jù)和函數(shù)
c通過type(built-in宠能,struct)創(chuàng)建出變量
C++通過class,struct(包含成員和函數(shù))創(chuàng)建出對象
類的經(jīng)典分類:帶指針(復(fù)數(shù))和不帶指針(string)
object based vs. object oriented
Object based:面對單一class的設(shè)計
Object Oriented:面對多重classes的設(shè)計,類之間的關(guān)系。
C++程序的代碼基本形式
.h (“ ”)+ .cpp + .h(標(biāo)準(zhǔn)庫,<>)
c和c++的輸出
cout和printf
頭文件中的guard聲明
第一次引用才定義,定義過則不過重復(fù)引用
#ifndef __header_name__
#define __header_name__
#endif
頭文件的布局
#ifndef __header_name__
#define __header_name__
1.前置聲明
class ostream;
class complex;
2.類-聲明
class complex
{
}
3.類-定義
complex::function..
#endif
class的聲明(declaration)
class complex //class head
{
//class body
}
模板(template)簡介
template<typename T>
構(gòu)造函數(shù)
inlinx(內(nèi)聯(lián))函數(shù)
函數(shù)在class body內(nèi)定義完成
運行較快。函數(shù)體簡單
(最終由編譯器決定是否為內(nèi)聯(lián))
(現(xiàn)在編譯器自動進行內(nèi)聯(lián)優(yōu)化)
access level 訪問級別
public
private
protect
構(gòu)造函數(shù) constructor
名稱同類名叶眉,不需要返回值類型。
構(gòu)造函數(shù)的特別語法↑
initialization list (大氣G奂稀P聘怼!)
簡單的差別:賦值過程不一樣鸳慈,能提高效率
不帶指針的類多半不用寫析構(gòu)函數(shù)
構(gòu)造函數(shù)可以有很多個--overloading(重載)
編譯器編譯后形成兩個名稱的函數(shù)
參數(shù)傳遞與返回值
singleton 單例 類
構(gòu)造函數(shù)放在private里
const member functions 常量成員函數(shù)
在函數(shù)后加const -->拿數(shù)據(jù)而不改變數(shù)據(jù)內(nèi)容
大家風(fēng)范饱溢!
參數(shù)傳遞:pass by value(形參) vs. pass by reference(to const)
引用& 在底層相當(dāng)于傳遞指針一樣快。
(侯捷老師:良好習(xí)慣:最好傳引用)
如果不想修改原引用值
使用const name&
參數(shù)一字節(jié)/兩字節(jié):可以形參
返回值傳遞:return by value vs. return by reference(to const)
返回值 如果可以--> 使用 引用傳遞
friend(友元)
友元函數(shù)可以自由取得friend 的 private成員
相同class的各個objects 互為friends(友元)
class body外的各種定義(definitions)
什么情況下可以pass by reference
什么情況下可以return by reference
- 一個函數(shù)運算結(jié)果的存放位置走芋,如果是新開辟的local 變量绩郎,則不可以使用引用。
- 運算結(jié)果存在位置在函數(shù)結(jié)束后不會釋放翁逞,則可以使用引用傳遞
操作符重載與臨時對象
操作符重載-1 operator overload 成員函數(shù) this
重載函數(shù)可以是成員函數(shù)或非成員函數(shù)
<< 只能寫成非成員函數(shù)
傳遞者無需知道接收者是以reference形式接收
臨時對象 typename();
--> return by value
類名typename(),-->創(chuàng)建一個臨時對象-->類似于int() 強制類型轉(zhuǎn)換肋杖?
注意點
- 考慮該不該加const
- 傳遞 是否用引用
- 返回是否用引用
- 數(shù)據(jù)放在private
- 函數(shù) 位置
復(fù)習(xí)complex類的實現(xiàn)過程
考慮函數(shù)是否加const
三大函數(shù):拷貝構(gòu)造、拷貝復(fù)制挖函、析構(gòu)函數(shù)
Class with pointer member
舉例:string class
指針類構(gòu)造函數(shù)設(shè)計
帶指針要自己寫賦值拷貝
框中一套函數(shù)
第二行 拷貝構(gòu)造
第三行 拷貝賦值(帶指針得類一定要寫)
第四行 析構(gòu)函數(shù)(釋放動態(tài)內(nèi)存分配到的內(nèi)存)
//一出手就要不同凡響
拷貝構(gòu)造
默認(rèn)的賦值會將兩個指針指向同一地址
而不是開辟一塊新的內(nèi)存地址存放字符串状植。
淺拷貝:指針拷貝,將第二個指針指向同一地址->可能會造成內(nèi)存泄漏
深拷貝:開辟一塊新的內(nèi)存空間怨喘,存放數(shù)據(jù)津畸,并將新的指針指向新的地址。
拷貝賦值函數(shù)
↑經(jīng)典寫法->大家風(fēng)范
先釋放掉自己必怜,然后new肉拓,然后拷貝。
一定要在op= 中檢查是否為自我賦值
堆 heap 棧stack 與內(nèi)存管理
介紹了heap梳庆、stack的概念 作用域
static 在作用域結(jié)束之后仍然存在暖途,直到程序結(jié)束
heap object 結(jié)束時需要delete 掉
new:先分配memory 再調(diào)用構(gòu)造函數(shù)
delete:先調(diào)用析構(gòu)函數(shù),再釋放memory
動態(tài)分配所得的memory block in VC
動態(tài)分配的array
array new [] 搭配 array delete []
復(fù)習(xí)string類的實現(xiàn)過程
模板類靠益、函數(shù)模板及其他
static
static靜態(tài)數(shù)據(jù)只有一份(記得 在類外 定義/初始化)
type classname::name = 8.0;
靜態(tài)函數(shù) 只能 存取 處理 靜態(tài)數(shù)據(jù)
調(diào)用static函數(shù)的方式:
1.通過對象調(diào)用
2.通過class name 調(diào)用
單例類 只有唯一一個
單例模式/singleton
cout
類模板 class template
template<typename T>
function template 函數(shù)模板
template<class T>
編譯器會自動推導(dǎo)出參數(shù)是哪類
特化/偏特化 等等
namespace
using directive残揉;//不用寫全名
using declaration胧后;//打開某一行或幾行
更多細(xì)節(jié)與深入
組合與繼承
類間的關(guān)系
- Inheritance(繼承
- Composition(復(fù)合
- Delegation(委托
composition(復(fù)合),表示has-a
類內(nèi)包含另一個類
//適配器模式
內(nèi)存觀察
composition關(guān)系下的構(gòu)造和析構(gòu)
構(gòu)造函數(shù)由內(nèi)而外
析構(gòu)函數(shù)由外而內(nèi)
Delegation(委托)抱环。compostion by reference
rep是指針指向(與復(fù)合相比壳快,壽命不一致纸巷,不是同步創(chuàng)建)
Inheritance(繼承),表示is-a
父類數(shù)據(jù)可以完全繼承
虛函數(shù)搭配最有價值
繼承下的構(gòu)造和析構(gòu)
- 構(gòu)造由內(nèi)而外:先父類眶痰,再子類
- 析構(gòu)由外而內(nèi):先子類再父類
虛函數(shù)與多態(tài)
繼承和虛函數(shù)
- non-virtual函數(shù):不希望子類重新定義的函數(shù)
- virtual函數(shù):希望子類重新定義瘤旨,并且已有默認(rèn)定義(可以是空虛函數(shù))
- pure virtual函數(shù):希望子類一定要重新定義,且沒有默認(rèn)定義
委托相關(guān)設(shè)計
23個經(jīng)典設(shè)計模式
- 類設(shè)計的三把大刀竖伯。(復(fù)合 委托 繼承)
導(dǎo)讀
conversion function 轉(zhuǎn)換函數(shù)
重載了double轉(zhuǎn)換類型
non-explicit-one-argument ctor
explicit關(guān)鍵字只能用于修飾只有一個參數(shù)的類構(gòu)造函數(shù), 它的作用是表明該構(gòu)造函數(shù)是顯示的, 而非隱式的, 跟它相對應(yīng)的另一個關(guān)鍵字是implicit, 意思是隱藏的,類構(gòu)造函數(shù)默認(rèn)情況下即聲明為implicit(隱式).
explicit關(guān)鍵字只對有一個參數(shù)的類構(gòu)造函數(shù)有效, 如果類構(gòu)造函數(shù)參數(shù)大于或等于兩個時, 是不會產(chǎn)生隱式轉(zhuǎn)換的, 所以explicit關(guān)鍵字也就無效了
這種情況會出現(xiàn)語法沖突存哲。
explicit-one-argument ctor
- explict 只用在構(gòu)造函數(shù)前
pointer-like classes,關(guān)于智能指針
智能指針->share_ptr->像指針的類
智能指針在語法上有三個很關(guān)鍵的地方七婴,第一個是保存的外部指針祟偷,對應(yīng)于上圖的T* px,這個指針將代替?zhèn)魅胫羔樳M行相關(guān)傳入指針的操作打厘;第二個是重載“*”運算符修肠,解引用,返回一個指針?biāo)赶虻膶ο蠡Фⅲ坏谌齻€是重載“->”運算符嵌施,返回一個指針,對應(yīng)于上圖就是px莽鸭。
關(guān)于迭代器
迭代器也是一種智能指針吗伤,這里也存在上面提到的智能指針的三個要素
注意操作符重載
創(chuàng)建一個list迭代器對象,list::iterator ite;這里的list用于保存Foo對象蒋川,也就是list模板定義里的class T牲芋,operator()返回的是一個(node).data對象,node是__link_type類型捺球,然而__link_type又是__list_node<T>類型缸浦,這里的T是Foo,所以node是__list_node<Foo>類型,所以(node).data得到的是Foo類型的一個對象氮兵,而&(operator())最終得到的是該Foo對象的一個地址裂逐,即返回Foo* 類型的一個指針。
function-like classes 仿函數(shù)
讓類像 一個函數(shù)泣栈?卜高?
“()”函數(shù)調(diào)用操作符(這我還真的第一次知道這么叫)
重載符號"()",就成為了一種仿函數(shù)
都會繼承一些奇怪的父類->在c++標(biāo)準(zhǔn)庫課程中講解
namespace 經(jīng)驗談
隔離一些可能命名重復(fù)的函數(shù)南片,避免沖突
class template掺涛,類模板
同之前
function template 函數(shù)模板
member template 成員模板
黃色代碼段本身是一個模板中的成員,它自身又是一個模板疼进。
成員模板在泛型編程里用得較多薪缆,為了有更好的可擴展性,以上圖為例伞广,T1往往是U1的基類拣帽,T2往往是U2的基類
通過這種方法疼电,只要傳入的U1和U2的父類或者祖類是T1和T2,那么通過這樣的方式可以實現(xiàn)繼承和多態(tài)的巧妙利用减拭,但反之就不行了蔽豺。這樣的方式在STL中用得很多
specialization 模板特化
泛化->模板
特化->模板中指定特定的數(shù)據(jù)類型
partial specialization 模板偏特化
1.個數(shù)上的偏
2.范圍上的偏
使用指針指向任意類型
template template parameter 模板的模板參數(shù)
容器需要好幾個模板參數(shù)
↑ list<int> 綁定好了類型,不算模板參數(shù)
關(guān)于c++標(biāo)準(zhǔn)庫
- 容器
- 算法
c++11在另一門課
三個主題
variadic templates(c++11) 數(shù)量不定的模板參數(shù)
允許寫任意個數(shù)的模板參數(shù) “..."已經(jīng)作為語法的一部分
多個模板參數(shù)進行遞歸調(diào)用拧粪。
auto
ranged-base for
for循環(huán)的新語法
reference
reference一定要有初值修陡。
初值設(shè)置之后不可以改變代表對象。
r = x2 一行相當(dāng)于給r賦值 使r為5 導(dǎo)致x也為5
const 是函數(shù)簽名的一部分
復(fù)合&繼承關(guān)系下的構(gòu)造與析構(gòu)
同之前
關(guān)于vptr和vtbl (虛指針既们、虛函數(shù)表
vptr指向vtbl 然后找到虛函數(shù)地址濒析,找到對應(yīng)函數(shù)
定義了三個類,A啥纸、B和C号杏,B繼承于A,C繼承于B,A中有兩個虛函數(shù)斯棒,B中有一個盾致,C中也有一個。編譯器將A的對象a在內(nèi)存中分配如上圖所示荣暮,只有兩個成員變量m_data1和m_data2庭惜,與此同時,由于A類有虛函數(shù)穗酥,編譯器將給a對象分配一個空間用于保存虛函數(shù)表护赊,這張表維護著該類的虛函數(shù)地址(動態(tài)綁定),由于A類有兩個虛函數(shù)砾跃,于是a的虛函數(shù)表中有兩個空間(黃藍空間)分別指向A::vfunc1()和A::vfunc2()骏啰;同樣的,b是B類的一個對象抽高,由于B類重寫了A類的vfunc1()函數(shù)判耕,所以B的虛函數(shù)表(青色部分)將指向B::vfunc1(),同時B繼承了A類的vfunc2()翘骂,所以B的虛函數(shù)表(藍色部分)將指向父類A的A::vfunc2()函數(shù)壁熄;同樣的,c是C類的一個對象碳竟,由于C類重寫了父類的vfunc1()函數(shù)草丧,所以C的虛函數(shù)表(黃色部分)將指向C::vfunc1(),同時C繼承了超類A的vfunc2()莹桅,所以B的虛函數(shù)表(藍色部分)將指向A::vfunc2()函數(shù)昌执。同時上圖也用C語言代碼說明了編譯器底層是如何調(diào)用這些函數(shù)的,這便是面向?qū)ο罄^承多態(tài)的本質(zhì)。
this指針
通過一個對象來調(diào)用仙蚜,對象的地址就是this
關(guān)于動態(tài)綁定 dynamic binding
STL源碼分析|c++標(biāo)準(zhǔn)庫體系結(jié)構(gòu)與內(nèi)核分析
認(rèn)識headers、版本厂汗、重要資源
使用一個東西委粉,卻不明白它的道理,不高明娶桦!
目標(biāo):使用c++標(biāo)準(zhǔn)庫-》認(rèn)識c++標(biāo)準(zhǔn)庫 ->良好使用c++標(biāo)準(zhǔn)庫->擴充c++標(biāo)準(zhǔn)庫