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關鍵字。
.