Boolan C 第五周學習筆記

2021-07-27 05:44:42 字數 2290 閱讀 8183

1.關於vptr和vtbl

之前的學習已經了解到c++多型主要靠虛函式實現,如果說c++的class在實現上相比c的struct有什麼開銷的話,那麼虛函式表(vtbl)的維護和每個物件例項裡虛表指標(vptr)將是比較明顯的開銷。

對於如下三個類

class a 

virtual void vfunc2()

void func1()

void func2()

};class b : public a

void funcb()

};class c : public b

void funcc()

};

非虛成員函式:a::func1(),a::func2(),b::funcb(),c::funcc()會單獨在記憶體裡存乙份

虛成員函式:a::vfunc1(),a::vfunc2(),b::vfunc1(),c::vfunc1()也會單獨存乙份,但是這四個虛函式會由虛函式表來記錄,由於這個例子裡有三個類,因此記憶體裡會有三份虛函式b::vfunc1(),a::vfunc2(),表,我們假設它們為a,b,c表。 a表裡會有兩個指標,分別指向a::vfunc1(),a::vfunc2()的位址,b表裡兩個指標,分別指向b::vfunc1(),a::vfunc2(),同理,c表裡的指標指向c::vfunc1(),a::vfunc2()。   

對於用基類指標new子類的情況:a *pa = new b; 這個例項物件裡放的也是b類對應的虛函式表,因為編譯器做了個向上轉型(upcasting)。

其實理解了虛函式表在記憶體的形式後,呼叫虛函式的**可以這麼表示: (*(pa->vptr)[n])(pa) 因為第乙個引數肯定是*this。

學習群裡u6th9d當時給我們提供了一些虛函式相關考驗題

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();

之前也提到,成員物件的第乙個內容是虛表,因此中間那段就是交換了物件裡的虛表指標,使得*pcat裡的vptr指向dog類的vtbl,*pdog的vptr指向cat類的vtbl,結果:

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並沒有表,我當時沒弄清楚,續表指標不是都變了嗎?為什麼呼叫的還是原來的函式呢?原因在於對動態繫結的理解

2.動態繫結

為了c++的多型性,是有動態繫結和靜態繫結這兩種說法的:

靜態繫結:繫結的物件是靜態型別,也就是編譯期就能決定的,是確定的,不會更改的,比如 a a; a的內容雖然會在執行期發生改變,但是a就是a,這點是不會變的。

動態繫結:繫結的物件是動態型別,動態型別就是指在編譯期無法決定的,因為它可能在執行期發生改變,比如指標:a* pa; pa可以在執行時重新指向其他物件,或者轉型指向b類或者c類。

通過vptr和vtbl實現虛函式是基於動態繫結的,因此基於指標呼叫的虛函式pcat,pdog呼叫的函式會隨著虛表指標的改變發生改變,但是用過普通物件直接呼叫,例如l07和l08,這是靜態繫結,在編譯期就已經決定了要呼叫的函式,因此不會改變。

第五周學習筆記

課程位址 第十三講,高斯混合模型 主要內容 值得注意的地方 1.em演算法的收斂 em演算法通過最大化似然函式的下界 使用jesen不等式得到 來近似最大化似然函式,其優化過程相當與對於其下界函式的座標上公升。2.高斯混合模型的優化 q step中的優化是乙個條件極值問題,約束是 j j 1 sig...

Boolan C 第二週學習筆記

第二週的課堂筆記,主要記錄一些以前自己不知道得東西。1.所謂的建構函式的三原則 其實預設情況下,編譯器缺省會提供拷貝構造,拷貝賦值,析構函式,它們所執行的就是預設的賦值與析構操作。並不是所有自定義的類都需要手動去寫這些函式,這次課程提供的乙個典型的情況就是類成員裡有指標時的情況,因為指標new出來的...

第五周學習筆記 201711671206

2.類的祖先類 object類 class a等同於class a object 3.在同乙個包中,子類繼承父類中的成員變數以及成員方法 除了private的 如果不在同乙個包裡面的話就繼承保護和公有的 4.成員變數的隱藏 所宣告的成員變數的名字和從父類繼承來的名字相同,子類就會隱藏繼承來的成員變數...