请考虑下面两个类:
class CBase
{
public:
virtual void Func(int *piVal) {...}
virtual void Func(float fVal) {...}
}
class CChild : public CBase
{
public:
virtual void Func(float fVal) {...}
}
void main(void)
{
int i = 0;
CBase *pB = new CChild;
CChild *pC = new CChild;
pB->Func(&i);
pB->Func(0.0f);
pC->Func(&i);
pC->Func(0.0f);
......
}
请回答我,main里面的4个Func调用,都能获得C++编译器认可吗?
被认可的调用里,分别都调哪个版本的Func函数?
说实话,这个问题,如果前天问我,我肯定答错。
先公布答案:
pB->Func(&i); 可以编译 调用CBase::Func(int *piVal)
pB->Func(0.0f); 可以编译 调用CChild::Func(float fVal)
pC->Func(&i); 不可以编译 ----
pC->Func(0.0f); 可以编译 调用CChild::Func(float fVal)
您答对了吗?原因是这样的:
pB->Func(0.0f)和pC->Func(0.0f)都可以编译,这个没什么可说的。它们都调用CChild::Func(float fVal),这正是“多态”的一种体现。我们也可以称这种现象为“晚绑定”。
pB->Func(&i);可以编译,这可能有人要说,这不是废话吗?但pC->Func(&i);为什么不能编译呢?
原来C++的设计者,为了避免“参数重载(Overload)”和“虚函数覆盖(Override)”在同一条继承路线上的不同层级同时发生,以致产生混乱,特意阻止了这样情况发生,他们定义了如下一条规矩,用白话可以这样说:
“覆盖(Override)”可以(并只能)发生在父子类之间;
“重载(Overload)”只发生在同一个类之内,不能夸继承层级发生。
当通过子类指针访问类对象时,如果子类拥有与父类重名的函数,则从子类的视角看,只能看到“覆盖(Override)”的发生,而看不到“重载(Overload)”了。