成员函数被重载的特征: //基类中
(1)相同的范围(在同一个类中);
(2)函数名字相同;
(3)参数不同;
(4)virtual关键字可有可无。
覆盖是指派生类函数覆盖基类函数,特征是: /基类与子类的关系
(1)不同的范围(分别位于派生类与基类);
(2)函数名字相同;
(3)参数相同;
(4)基类函数必须有virtual关键字。
“隐藏”是指派生类的函数屏蔽了与其同名的基类函数,规则如下: 子类中
(1)如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。
(2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)。
#include
class B {
public:
void mf(){cout<<"1 ";};
};
class D: public B {
public:
void mf(){cout<<"2 ";};
};
main(){
D x;
B *pB = &x;
pB->mf();
D *pD = &x;
pD->mf();
//B bb;
// bb.mf();
}
两种情况下调用的都是对象x的成员函数mf,因为两种情况下都是相同的函数和相同的对象,所以行为会相同,对吗?
对,会相同。但,也许不会相同。特别是,如果mf是非虚函数而D又定义了自己的mf版本,行为就不会相同.
1)当类B中有虚函数mf()时,类D中没有重写此函数时,结果为:1 1。 一般的继承
2)当类B中有虚函数mf()时,类D中重写此函数时,结果为:2 2。 派生类函数覆盖基类函数(基类本身是虚函数,所以指向了子类)
3)当类B中有非虚函数mf()时,类D中没有重写此函数时,结果为:1 1。 一般的继承
4)当类B中有非虚函数mf()时,类D中重写此函数时,结果为:1 2。 类D中的函数隐藏了从基类B中继承下来的函数
5)当类B中有虚或非虚函数mf()时,类D中有与此函数同名但时参数不同的函数时,从基类继承而来的函数也被隐藏!
掌握了这么多看似很充分的知识,去应用的时候又不灵活,见如下的题目
#include <stdio.h>
class Base1
{
public:
void bar (float a){printf("base::int bar (float a)\n");}
virtual void bar (int a){printf("base::int bar (int a)\n");}
};
class Device:public Base1
{
public:
void bar (float a){printf("device::int bar (float a)\n");}
void bar (int a){printf("device::int bar (int a)\n");}
};
void main()
{
Base1 *p=new Device;
p->bar(100);
p->bar((float)100);
Device *q= new Device;
q->bar(100);
q->bar((float)100);
}
其中运行结果是
device::int bar (int a)
base::int bar (float a)
device::int bar (int a)
device::int bar (float a)
其中对比上面除了一般继承外的四种情况
第一种是覆盖
第二种是无情况
第三种是隐藏
第四种也是隐藏(原来基类是基类本身的调用而言的)
第四种给个假设,如果基类中没有float函数,然后父类中有,这里同样是被隐藏