文章目录
- 多态
- 虚函数
多态
- 多态性是面向对象程序设计语言的又一重要特征,多态(polymorphism)通俗地讲,就是用一个相同的名字定义许多不同的函数,这些函数可以针对不同数据类型实现相同或相似的功能,即所谓的“一个接口,多种实现”
#include<iostream>usingnamespacestd;classShape{public:virtualvoiddraw(void){cout<<"draw shape"<<endl;}};classRect:publicShape{public:voiddraw(void){cout<<"draw Rect"<<endl;}};classCircle:publicShape{public:voiddraw(void){cout<<"draw Circle"<<endl;}};classEllipse:publicShape{public:voiddraw(void){cout<<"draw Ellipse"<<endl;}};intmain(void){/* Ellipse e; e.draw(); e.Shape::draw(); */Shape*buf[128]={0};buf[0]=newRect;buf[1]=newCircle;buf[2]=newEllipse;for(inti=0;buf[i]!=NULL;i++){buf[i]->draw();}return0;}虚函数
- 被virtual关键字修饰的成员函数称为虚函数
- 如果将基类中的某个成员函数声明为虚函数,那么子类中与该函数具有相同原型的成员函数就也是虚函数,并且对基类中版本形成覆盖,即函数重写
- 如果子类提供了对基类虚函数有效的覆盖,那么通过指向子类对象的基类指针,或者通过引用子类对象基类引用,调用该虚函数,实际被执行将是子类中的覆盖版本,而不再是基类中原始版本,这种语法现象被称为多态
- 多态的意义在于,一般情况下,调用哪个类的成员函数由调用者指针或者引用本身类型决定的, 而有了多态,调用哪个类的成员函数由调用者指针或者引用实际目标对象的类型决定
- 这样一来,源自同一种类型的同一种激励,竟然可以产生多种不同的响应,也就是对于同一个函数调用,能够表达出不同的形态,即为多态
- 虚函数覆盖的条件:
- 只有类中的成员函数才能声明为虚函数,而全局函数、静态成员函数、构造函数都不能被声明为虚函数
- 只有在基类中以virtual关键字声明的虚函数,才能作为虚函数被子类覆盖,而与子类中的virtual关键字无关
- 虚函数在子类中的版本和基类中版本要具有相同的函数签名,即函数名、参数表、常属性一致
- 如果基类虚函数返回基本类型的数据,那么子类中的版本必须返回相同类型的数据;如果基类虚函数返回类类型指针(A)或引用(A&),那么允许子类中的版本返回其子类类型指针(B)或引用(B&)
#include<iostream>usingnamespacestd;classA{};classB:publicA{};classBase{public:virtualvoidfunc(void){cout<<"Base func"<<endl;}virtualA*foo(void){cout<<"Base foo"<<endl;}};classDerived:publicBase{voidfunc(void){cout<<"Derived func"<<endl;}B*foo(void){cout<<"Derived foo"<<endl;}};intmain(void){Derived d1;Base*pd1=&d1;pd1->func();Base&pd2=d1;pd2.foo();return0;}- 产生多态的条件:
- 除了要满足函数重写的语法要求,还必须是通过指针或引用调用虚函数,才能表现出来
#include<iostream>usingnamespacestd;classA{};classB:publicA{};classBase{public:virtualvoidfunc(void){cout<<"Base func"<<endl;}virtualA*foo(void){cout<<"Base foo"<<endl;}};classDerived:publicBase{voidfunc(void){cout<<"Derived func"<<endl;}B*foo(void){cout<<"Derived foo"<<endl;}};intmain(void){Derived d1;Base b=d1;b.func();//实际上调用 base中的funcreturn0;}- 调用虚函数的指针也可以是this指针,当使用子类对象调用基类中的成员函数时,该函数里面this指针将是一个指向子类对象的基类指针,再通过this去调用满足重写要求的虚函数同样可以表现多态的语法特性
#include<iostream>usingnamespacestd;classA{};classB:publicA{};classBase{public:virtualvoidfunc(void){cout<<"Base func"<<endl;}A*foo(void){//this->func();func();}};classDerived:publicBase{voidfunc(void){cout<<"Derived func"<<endl;}};intmain(void){Derived d1;d1.foo();return0;}