国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > C++ > 正文

[Boolan] C++第五周學(xué)習(xí)筆記

2019-11-08 01:46:41
字體:
供稿:網(wǎng)友

1.關(guān)于vptr和vtbl

    之前的學(xué)習(xí)已經(jīng)了解到c++多態(tài)主要靠虛函數(shù)實現(xiàn),如果說c++的class在實現(xiàn)上相比c的struct有什么開銷的話,那么虛函數(shù)表(vtbl)的維護(hù)和每個對象實例里虛表指針(vptr)將是比較明顯的開銷。

    對于如下三個類

class A {public:	virtual void vfunc1() { cout << "A::vfunc1/n"; }	virtual void vfunc2() { cout << "A::vfunc2/n"; }	void func1() { cout << "A::func1/n"; }	void func2() { cout << "A::func2/n"; }};class B : public A {public:	virtual void vfunc1() { cout << "B::vfunc1/n"; }	void funcb() { cout << "B::funcb/n"; }};class C : public B {public:	virtual void vfunc1() { cout << "C::vfunc1/n"; }	void funcc() { cout << "C::funcc/n"; }};

    非虛成員函數(shù):A::func1(),A::func2(),B::funcb(),C::funcc()會單獨在內(nèi)存里存一份

    虛成員函數(shù):A::vfunc1(),A::vfunc2(),B::vfunc1(),C::vfunc1()也會單獨存一份,但是這四個虛函數(shù)會由虛函數(shù)表來記錄,由于這個例子里有三個類,因此內(nèi)存里會有三份虛函數(shù)B::vfunc1(),A::vfunc2(),表,我們假設(shè)它們?yōu)锳,B,C表。 A表里會有兩個指針,分別指向A::vfunc1(),A::vfunc2()的地址,B表里兩個指針,分別指向B::vfunc1(),A::vfunc2(),同理,C表里的指針指向C::vfunc1(),A::vfunc2()。   

    對于用基類指針new子類的情況:A *pa = new B; 這個實例對象里放的也是B類對應(yīng)的虛函數(shù)表,因為編譯器做了個向上轉(zhuǎn)型(upcasting)。

    其實理解了虛函數(shù)表在內(nèi)存的形式后,調(diào)用虛函數(shù)的代碼可以這么表示: (*(pa->vptr)[n])(pa) 因為第一個參數(shù)肯定是*this。

    學(xué)習(xí)群里u6th9d當(dāng)時給我們提供了一些虛函數(shù)相關(guān)考驗題

	Cat cat("cat");	Dog dog("dog");	Animal* pcat = &cat;	Animal* pdog = &dog;	std::cout << "L01: ";	pcat->say();	std::cout << "L02: ";	pdog->say();	std::cout << "L03: ";	cat.say();	std::cout << "L04: ";	dog.say();	void* tmp = ((void**)pcat)[0];	((void**)pcat)[0] = ((void**)pdog)[0];	((void**)pdog)[0] = tmp;	std::cout << "L05: ";	pcat->say();	std::cout << "L06: ";	pdog->say();	std::cout << "L07: ";	cat.say();	std::cout << "L08: ";	dog.say();

    之前也提到,成員對象的第一個內(nèi)容是虛表,因此中間那段就是交換了對象里的虛表指針,使得*pcat里的vptr指向Dog類的vtbl,*pdog的vptr指向Cat類的vtbl,結(jié)果:

L01: cat miaomiao~~L02: dog wangwang~~L03: cat miaomiao~~L04: dog wangwang~~L05: cat wangwang~~L06: dog miaomiao~~L07: cat miaomiao~~L08: dog wangwang~~

    L05和L06確實交換了,但是L07和L08并沒有表,我當(dāng)時沒弄清楚,續(xù)表指針不是都變了嗎?為什么調(diào)用的還是原來的函數(shù)呢?原因在于對動態(tài)綁定的理解

2.動態(tài)綁定

    為了C++的多態(tài)性,是有動態(tài)綁定和靜態(tài)綁定這兩種說法的:

    靜態(tài)綁定:綁定的對象是靜態(tài)類型,也就是編譯期就能決定的,是確定的,不會更改的,比如 A a; a的內(nèi)容雖然會在運行期發(fā)生改變,但是a就是a,這點是不會變的。

    動態(tài)綁定:綁定的對象是動態(tài)類型,動態(tài)類型就是指在編譯期無法決定的,因為它可能在運行期發(fā)生改變,比如指針:A* pa; pa可以在運行時重新指向其他對象,或者轉(zhuǎn)型指向B類或者C類。

    這邊文章很好地總結(jié)了靜態(tài)綁定和動態(tài)綁定:https://www.oschina.net/question/54100_20313

    通過vptr和vtbl實現(xiàn)虛函數(shù)是基于動態(tài)綁定的,因此基于指針調(diào)用的虛函數(shù)pcat,pdog調(diào)用的函數(shù)會隨著虛表指針的改變發(fā)生改變,但是用過普通對象直接調(diào)用,例如L07和L08,這是靜態(tài)綁定,在編譯期就已經(jīng)決定了要調(diào)用的函數(shù),因此不會改變。


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表

圖片精選

主站蜘蛛池模板: 新化县| 界首市| 柳州市| 阆中市| 靖西县| 邢台县| 达尔| 阿坝| 启东市| 定南县| 西乌珠穆沁旗| 驻马店市| 广安市| 莲花县| 郑州市| 太保市| 五指山市| 长岛县| 壶关县| 射洪县| 万全县| 旅游| 蚌埠市| 邛崃市| 南投市| 巧家县| 大英县| 德庆县| 凤阳县| 农安县| 沛县| 民乐县| 那曲县| 思南县| 阳谷县| 工布江达县| 桂平市| 襄垣县| 延边| 丰城市| 元谋县|