1:函数重写
如果子类当中定义了与父类当中原型相同的函数会怎么样?
函数重写:
在子类中定义与父类原型相同的函数;
函数重写只发生在父类与子类之间;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */ /* 函数重写: 父类中被重写的函数依然会继承给子类 默认情况下子类中重写的函数将隐藏父类中的函数 通过作用域分辨符::可以访问到父类中被隐藏的函数 2014年9月3日19:51:11 */ #include <iostream> using namespace std; class Parent { public: void print() { cout<<"I'm a Parent"<<endl; } }; class Child: public Parent { public: void print() { cout<<"I'm a Child"<<endl; } }; int main(int argc, char** argv) { Child child; child.print();//函数重写 child.Parent::print(); return 0; }
函数重写遇上赋值兼容性原则:
#include <iostream> using namespace std; class Parent { public: void print() { cout<<"I'm a Parent"<<endl; } }; class Child: public Parent { public: void print() { cout<<"I'm a Child"<<endl; } }; void run() { Child child; Parent* pp = &child; Parent& rp = child; child.print(); pp->print(); rp.print(); } void howToPrint(Parent* p) { p->print(); } int main(int argc, char** argv) { cout<<"............................."<<endl; run(); /* C++与C相同,是静态编译型语言 在编译时,编译器自动根据指针的类型判断指向的是一个什 么样的对象 所以编译器认为父类指针指向的是父类对象(根据赋值兼容 性原则,这个假设合理) 由于程序没有运行,所以不可能知道父类指针指向的具体是 父类对象还是子类对象 从程序安全的角度,编译器假设父类指针只指向父类对象, 因此编译的结果为调用父类的成员函数 */ cout<<"*******************************"<<endl; Parent *p; Child *q; howToPrint(p);//输出为 "I'm a Parent" howToPrint(q);//输出为 "I'm a Parent" /* 在编译这个函数的时候,编译器不可能知道指针 p 究 竟指向了什么。但是编译器没有理由报错。于是,编 译器认为最安全的做法是编译到父类的print函数,因 为父类和子类肯定都有相同的print函数。 */ return 0; }
C++与C相同,是静态编译型语言
在编译时,编译器自动根据指针的类型判断指向的是一个什
么样的对象
所以编译器认为父类指针指向的是父类对象(根据赋值兼容
性原则,这个假设合理)
由于程序没有运行,所以不可能知道父类指针指向的具体是
父类对象还是子类对象
从程序安全的角度,编译器假设父类指针只指向父类对象,
因此编译的结果为调用父类的成员函数
由上面我们引出了多态:
面向对象的新需求
根据实际的对象类型来判断重写函数的调用
如果父类指针指向的是父类对象则调用父类中定义
的函数
如果父类指针指向的是子类对象则调用子类中定义
的重写函数
面向对象中的多态:
根据实际的对象类型决定函数调用语句的具体调用目标;
多态:同样的调用语句有多种不同的表现形态;
p->print();
当p指向父类对象的时候,调用父类的print()函数;
当p指向子类对象的时候,调用子类的print()函数;
C++中的多态支持:
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() { Boss* boss = Boss::GetInstance(); cout<<"Master VS Boss:"<<endl; Master master; fieldPK(&master,boss); cout<<"newMaster VS Boss:"<<endl; NewMaster newMaster; fieldPK(&newMaster,boss); cin.get(); } /* 多态的本质 面向对象的新需求 根据实际的对象类型来判断重写函数的调用 如果父类指针指向的是父类对象则调用父类中定义 的函数 如果父类指针指向的是子类对象则调用子类中定义 的重写函数 面向对象中的多态 根据实际的对象类型决定函数调用语句的具体调用目标 多态:同样的调用语句有多种不同的表现形态 C++中的多态支持 C++中通过virtual关键字对多态进行支持 使用virtual声明的函数被重写后即可展现多态特性 小结: 函数重写是面向对象中很可能发生的情形 函数重写只可能发生在父类与子类之间 需要根据实际对象的类型确定调用的具体函数 virtual关键字是C++中支持多态的唯一方式 被重写的虚函数即可表现出多态的特性 */