多態體驗,和探索爺爺類指針的多態性
- 2020 年 10 月 3 日
- 筆記
- C++語言--與時俱進
1. 多態初體驗
#include <iostream> #include <string> using namespace std; class Parent { public: virtual void print() { cout << "I'm Parent." << endl; } }; class Child : public Parent { public: void print() { cout << "I'm Child." << endl; } }; void how_to_print(Parent* p) { p->print(); } int main() { Parent p; Parent*pfather = &p; Child c; Parent* pson = reinterpret_cast<Parent*>(&c); Parent* p = pson; // p也具備多態性 how_to_print(pfather); how_to_print(pson); how_to_print(p); pson_2 = pfather; how_to_print(p); return 0; }
現象:p具備多態性
小結: 指向子類對象的父類指針被傳遞後,依然具備多態性。
2. 探索爺爺類的多態
實驗一:
爺爺類(父類的父類)是抽象類,看能否在孫類(子類的子類)身上,實現一個方法(成員函數)的多態調用。
#include <iostream> #include <string> using namespace std; class Parent { public: virtual void print() = 0; }; #if 0 // 方式1 class Child : public Parent { public: virtual void print() = 0; }; #else // 方式2 class Child : public Parent { public: void print() { cout << "Child: print()" << endl; } }; #endif class GrandSon : public Child { string name; public: GrandSon(char* n_name) { name = string(n_name); } void print() { cout << "GrandSon::print() :" << name << endl; } }; void how_to_print(Parent* p) { p->print(); } int main() { GrandSon gson1("jason"); how_to_print(reinterpret_cast<Parent*>(&gson1)); Parent* pgson1 = reinterpret_cast<Parent*>(&gson1); cout << endl; GrandSon gson2("polly"); Parent* pgson2 = reinterpret_cast<Parent*>(&gson2); how_to_print(pgson2); cout << endl; // 下面是拓展實驗 Parent* gson_current = pgson1; how_to_print(gson_current); return 0; }
小結: 爺爺類(父類的父類)是抽象類時,中間層的父類是抽象類也罷,或者實現了自己的多態方法也罷,此時, 當爺爺類指針指向孫類對象,依然具備多態特性。
實驗二:
爺爺類(父類的父類)是非抽象類,看能否在孫類(子類的子類)身上,實現一個方法(成員函數)的多態調用。
#include <iostream> #include <string> using namespace std; class Parent { public: virtual void print() { cout << "Parent:: print()" << endl; } }; class Child : public Parent { public: void print() { cout << "Child:: print()" << endl; } }; class GrandSon : public Child { string name; public: GrandSon(char* n_name) { name = string(n_name); } void print() { cout << "GrandSon::print() :" << name << endl; } }; void how_to_print(Parent* p) { p->print(); } int main() { GrandSon gson1("jason"); how_to_print(reinterpret_cast<Parent*>(&gson1)); Parent* pgson1 = reinterpret_cast<Parent*>(&gson1); cout << endl; GrandSon gson2("polly"); Parent* pgson2 = reinterpret_cast<Parent*>(&gson2); how_to_print(pgson2); cout << endl; // 下面是拓展實驗 Parent* gson_current = pgson1; how_to_print(gson_current); return 0; }
爺爺類是非抽象類,實現了自己的virtual的方法A,且父類也實現了自己的virtual的方法A,且子類也實現了自己的virtual的方法A, 此時, 當爺爺類指針指向孫類對象,依然具備多態特性。
最終結論:
只要調用的成員函數自從爺爺類開始就是virtual修飾的,使用爺爺類的指針指向孫類對象時,就支持多態調用。
如果你需要一個精簡版理解,那麼你只需要理解:
多態調用的精髓在於使用了virtual關鍵字。
.