多态与继承_16
一。函数重写
1.在子类中定义与父类中原型相同的函数
2.函数重写只发生在父类与子类之间
#include <cstdlib> #include <iostream> using namespace std; class Parent { public: void Print() { cout << "Parent()" << endl; } }; class Child : public Parent { public: void Print() { cout <<"Child()"<< endl; } }; void run() { Child child; child.Print(); } int main(int argc, char *argv[]) { run(); cout << "Press the enter key to continue ..."; cin.get(); return EXIT_SUCCESS; }
3.父类中被重写的函数依然会继承给子类
4.默认情况下子类的重写函数会掩藏父类的函数
5.通过作用域分辨符::可以访问到父类中被隐藏的函数
二。当函数重写遇上了赋值兼容性原则
void run() { Child child; Parent* pp = &child; Parent& rp = child; child.Print(); pp -> Print(); rp.Print(); }
问题所在:
1.在C++和C相同,是静态编译型语言
2.在编译时,编译器自动根据指针的类型判断指向是一个什么样的对象
3.所以编译器认为父类指针是指向的父类对象(根据赋值兼容性原则,则这个假设合理)
4.由程序没有执行,所以不知道父类指针指向的具体是父类对象还是子类对象
5.从程序安全的角度,编译器假设父类指针只指向父类对象,因此编译的结果为调父类的成员函数。
三。多态的本质
1.面向对象的新需求
a.根据实际的对象类型来判断重写函数的调用
b.父类对象指向父类的函数。
2.面向对象中的多态:
根据实际的对象类型决定函数调用语句的具体调用目标
3.c++中通过virtual 关键字对多态进行支持
使用virtual声明的函数被重写后即可展现多态特性 - 这就是传说中的虚函数
#include <cstdlib> #include <iostream> using namespace std; class Boss { private: static Boss* cInstance; Boss() { } public: static Boss* GetInstance() { if( cInstance == NULL ) { cInstance = new Boss(); } return cInstance; } int fight() { cout<<"Boss::fight()"<<endl; return 10; } }; Boss* Boss::cInstance = NULL; class Master { public: virtual int eightSwordKill() { cout<<"Master::eightSwordKill()"<<endl; return 8; } }; class NewMaster : public Master { public: virtual int eightSwordKill() { cout<<"NewMaster::eightSwordKill()"<<endl; return Master::eightSwordKill() * 2; } }; void fieldPK(Master* master, Boss* boss) { int k = master->eightSwordKill(); int b = boss->fight(); if( k < b ) { cout<<"Master is killed..."<<endl; } else { cout<<"Boss is killed..."<<endl; } } int main(int argc, char *argv[]) { Boss* boss = Boss::GetInstance(); cout<<"Master vs Boss"<<endl; Master master; fieldPK(&master, boss); cout<<"New Master vs Boss"<<endl; NewMaster newMaster; fieldPK(&newMaster, boss); cout << "Press the enter key to continue ..."; cin.get(); return EXIT_SUCCESS; }
四。小结
1.函数重写是面向对象中很可能发生的情形
2.函数重写只可发生在父类和子类之间
3.需要根据实际对象的类型确定调用的具体函数
4.virtual 关键字是c++中支持多态的唯一方式
5.被重写的虚函数即可表现多态的特性。