一,多态性
1,(1)声明了基类的指针,该指针指向基类,该指针永远调用自己的成员函数,不管函数是否为虚函数。
(2)声明了派生类的指针,该指针指向该派生类,该指针永远调用自己的成员函数,不管函数是否为虚函数。
(3)声明了基类的指针,该指针指向任意一个子类对象,该指针调用一个函数(此函数在基类存在,而且在子类中被重新定义),此时编译系统不清楚该调用哪一个函数,而出错。我们可以将该函数设定为虚函数,则程序运行时候,编译系统会知道调用的是基类函数还是子类函数,此即多态。注:如果调用的函数不是虚函数,则调用自己类中的成员函数。如果指针被声明为基类,尽管它指向子类对象,仍然是基类指针。
2,子类重定义父类成员函数方法,被称为覆盖或重写。覆盖的函数都是虚函数。
3,满足虚函数条件或覆盖的特征是:
(1)不同的范围(分别位于派生类与基类);
(2)函数名字相同;
(3)参数相同;
(4)基类函数必须有virtual 关键字。
二,成员函数重载
成员函数被重载的特征:
(1)相同的范围(在同一个类中);
(2)函数名字相同;
(3)参数不同;
(4)virtual 关键字可有可无。
三,成员函数隐藏
看如下代码:
Base.h
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> using namespace std; class Base{ public: void fn(int x){ cout << "Base" << x << endl; } void fn1(int x){ cout << "Base1" << x << endl; } };
SubClass.h
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> using namespace std; class SubClass :public Base{ public: void fn(float x){ cout << "SubClass" << x << endl; } void fn1(int x){ cout << "SubClass1" << x << endl; } };
main.cpp
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include "A.h" #include "B.h" #include "C.h" using namespace std; int main() { C c(10); cout << c.GetData() << endl; cout << c.A::GetData() << endl; cout << c.B::GetData() << endl; cout << c.C::GetData() << endl; cout << c.doGetData() << endl; cout << c.A::doGetData() << endl; cout << c.B::doGetData() << endl; cout << c.C::doGetData() << endl; return 0; }
运行结果:
fn()函数不符合虚函数条件,不是虚函数。
从SubClass角度来说,其有void fn(float x)函数,从Base继承了void fn(int x)函数,因此这两个函数在SubClass内应该是重载的,因此主函数中SubClass对象sc,sc.fn(3.1f)应该调用void fn(float x)函数,sc.fn(1)应该调用void fn(int x),但是运行结果显示两个都调用了void fn(float x)函数,这是因为Base中的void fn(int x)函数被隐藏了。
主函数中sc.fn1(2);时候,通过结果知道调用了void fn1(int x)函数,Base中的void fn1(int x)函数被隐藏了。
因此知道符合函数隐藏条件是:
(1)如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏。注意别与重载混淆。
(2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字。此时,基类的函数被隐藏。注意别与覆盖混淆。