嘿,各位技術潮人!好久不見甚是想念。生活就像一場奇妙冒險,而編程就是那把超酷的萬能鑰匙。此刻,陽光灑在鍵盤上,靈感在指尖跳躍,讓我們拋開一切束縛,給平淡日子加點料,注入滿滿的passion。準備好和我一起沖進代碼的奇幻宇宙了嗎?Let's go!
我的博客:yuanManGan
我的專欄:C++入門小館?C言雅韻集?數據結構漫游記? 閑言碎語小記坊?題山采玉?領略算法真諦
目錄
多態的概念:
構成多態的條件:
虛函數:
虛函數的重寫/覆蓋:
? 協變(了解)
析構函數的重寫:
override 和 final關鍵字
重載/重寫/隱藏的對?
?純虛函數和抽象類
多態的原理:
虛函數表指針:
虛函數表:
面向對象三大特性:封裝,繼承,多態。今天來講講最后一個多態。
多態的概念:
多態是針對函數來說的,當函數名相同時,我們傳入不同的參數會出現不同的效果,這就是多態。多態又分為靜態多態,和動態多態,靜態指的一般是函數重載和模板(又叫作編譯時多態),而我們今天的重點是動態多態(也叫作運行時多態)
動態多態就是,當你傳入不同的對象時(函數),會出現不一樣的結果,比如我們買火車票,如果你是學生會打折,成人就是全票,而軍人就是優先買票。再?如,同樣是動物叫的?個?為(函數),傳貓對象過去,就是”(>^ω^<) 喵“,傳狗對象過去,就是"汪汪"。
構成多態的條件:
這里補充一下:
虛函數:
虛函數的重寫/覆蓋:
class Person {
public:virtual void BuyTicket() { cout << "買票-全價" << endl; }
};
class Student : public Person {
public:virtual void BuyTicket() { cout << "買票-打折" << endl; }
};
void Func(Person* ptr)
{// 這?可以看到雖然都是Person指針Ptr在調?BuyTicket// 但是跟ptr沒關系,?是由ptr指向的對象決定的。ptr->BuyTicket();
}
int main()
{Person ps;Student st;Func(&ps);Func(&st);return 0;
}
?
class Animal
{
public:virtual void talk() const{}
};
class Dog : public Animal
{
public:virtual void talk() const{std::cout << "汪汪" << std::endl;}
};
class Cat : public Animal
{
public:virtual void talk() const{std::cout << "(>^ω^<)喵" << std::endl;}
};
void letsHear(const Animal& animal)
{animal.talk();
}
int main()
{Cat cat;Dog dog;letsHear(cat);letsHear(dog);return 0;
}
這里的對虛函數的重寫,其實是重寫的實現。
? 協變(了解)
class A {};
class B : public A {};
class Person {
public:virtual A* BuyTicket(){cout << "買票-全價" << endl;return nullptr;}
};
class Student : public Person {
public:virtual B* BuyTicket(){cout << "買票-打折" << endl;return nullptr;}
};
void Func(Person* ptr)
{ptr->BuyTicket();
}
int main()
{Person ps;Student st;Func(&ps);Func(&st);return 0;
}
這樣寫沒有很大的意義,我們很少這么實現。
析構函數的重寫:

我們定義了兩個A類型的指針分別指向A和B對象,但我們析構時為什么沒有析構B對象呢?因為我們的p2是指向A類型的,然后我們析構是調用A類型的析構。那我們該怎樣調用B的析構函數呢?這里就要用到多態了,但我們的析構的函數名不是不相同嗎,怎么實現重寫呢?其實編譯器會將你寫的析構函數的函數名看成一樣的Destruct,這就導致我們繼承遇到的析構函數為什么會隱藏,這里將A的析構寫成隱藏就可以解決了。
override 和 final關鍵字
override 用來檢查一個虛函數是否被重寫,沒有就會報錯。
重載/重寫/隱藏的對?
?純虛函數和抽象類
在虛函數的后?寫上 =0 ,則這個函數為純虛函數,純虛函數不需要定義實現(實現沒啥意義因為要被 派?類重寫,但是語法上可以實現),只要聲明即可。包含純虛函數的類叫做抽象類,抽象類不能實例 化出對象,如果派?類繼承后不重寫純虛函數,那么派?類也是抽象類。純虛函數某種程度上強制了 派?類重寫虛函數,因為不重寫實例化不出對象。
多態的原理:
虛函數表指針:

該程序的運行結果(32位的環境下)是什么呢?
有人說是8不就是兩個成員嗎,內存對齊一下就是8,其實我們有虛函數的類里面還有一個虛函數表指針,指向虛函數表。
?所以答案是12。
我們實現虛函數的重寫其實就是將虛函數表指針進行重寫。使他指向不同的對象,我們無論傳入的派生類是怎么樣的,傳入Func函數都會進行截斷,是它只出現父類,然后通過虛函數表指針調用函數,這就形成了多態。
虛函數表:

