C++.png
多態(tài)
默認(rèn)情況下射窒,編譯器只會(huì)根據(jù)指針類型調(diào)用對應(yīng)的函數(shù)藏杖,不存在多態(tài)
-
多態(tài)是面向?qū)ο蠓浅V匾囊粋€(gè)特性
- 同一操作作用于不同的對象,可以有不同的解釋脉顿,產(chǎn)生不同的執(zhí)行結(jié)果
- 在運(yùn)行時(shí)蝌麸,可以識(shí)別出真正的對象類型,調(diào)用對應(yīng)子類中的函數(shù)
-
多態(tài)的要素
- 子類重寫父類的成員函數(shù)(override)
- 父類指針指向子類對象
- 利用父類指針調(diào)用重寫的成員函數(shù)
虛函數(shù)
- C++中的多態(tài)通過虛函數(shù)(virtual function)來實(shí)現(xiàn)
- 虛函數(shù):被virtual修飾的成員函數(shù)
- 只要在父類中聲明為虛函數(shù)艾疟,子類中重寫的函數(shù)也自動(dòng)變成虛函數(shù)(也就是說子類中可以省略virtual關(guān)鍵字)
虛表
虛函數(shù)的實(shí)現(xiàn)原理是虛表来吩,這個(gè)虛表里面存儲(chǔ)著最終需要調(diào)用的虛函數(shù)地址敢辩,這個(gè)虛表也叫虛函數(shù)表
struct Animal {
int m_age;
virtual void speak(){
cout << "Animal::speak()" << endl;
}
virtual void run(){
cout << "Animal::run()" << endl;
}
};
struct Cat: Animal {
int m_life;
virtual void speak(){
cout << "Cat::speak()" << endl;
}
virtual void run(){
cout << "Cat::run()" << endl;
}
};
int main() {
Animal *cat =new Cat();
cat->speak();
cat->run();
return 0;
}
// log:
Cat::speak()
Cat::run()
注意,一定要指針弟疆,如果是對象戚长,就失靈了。多態(tài)的三要素缺一不可怠苔。
int main() {
Animal cat = Cat();
cat.speak();
cat.run();
return 0;
}
// log:
Animal::speak()
Animal::run()
虛表(x86環(huán)境的圖)
調(diào)用父類的成員函數(shù)實(shí)現(xiàn)
class Animal {
public:
virtual void speak(){
cout << "Animal::speak()" << endl;
}
};
class Cat: public Animal {
public:
void speak(){
Animal::speak();
cout << "Cat::speak()" << endl;
}
};
int main() {
Animal cat = Cat();
cat.speak();
return 0;
}
// log:
Animal::speak()
Q:為啥不繼續(xù)執(zhí)行下面的代碼
A:上面不是多態(tài)
int main() {
Animal *cat = new Cat();
cat->speak();
return 0;
}
// log:
Animal::speak()
Cat::speak()
虛析構(gòu)函數(shù)
- 含有虛函數(shù)的類同廉,應(yīng)該將析構(gòu)函數(shù)聲明為虛函數(shù)(虛析構(gòu)函數(shù))
- delete父類指針時(shí),才會(huì)調(diào)用子類的析構(gòu)函數(shù)柑司,保證析構(gòu)的完整性
class Animal {
public:
virtual void speak(){
cout << "Animal::speak()" << endl;
}
virtual ~Animal(){
cout << "Animal::~Animal()" << endl;
}
};
class Cat: public Animal {
public:
void speak(){
Animal::speak();
cout << "Cat::speak()" << endl;
}
~Cat(){
cout << "Animal::~Cat()" << endl;
}
};
int main() {
Animal *cat = new Cat();
cat->speak();
return 0;
}
// log:
Animal::speak()
Cat::speak()
Q:為啥不析構(gòu)