多态体验,和探索爷爷类指针的多态性
- 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关键字。
.