一、重载(overload):
特征: 函数名相同 、函数参数不同、 必须位于同一个域(类)中;
注意,返回值类型不相同,不能作为重载的判断条件。
二、覆盖(override):
特征: 函数名相同 、函数参数相同、 分别位于派生类和基类中、virtual(虚函数);
三、隐藏(hide/Overwrite(重写)):
即:派生类中函数隐藏(屏蔽)了基类中的同名函数。
情形1: 函数名相同、 函数参数相同、 分别位于派生类和基类中、virtual -- 为 覆盖;
情形2: 函数名相同、 函数参数相同、 分别位于派生类和基类中 -- 为 隐藏;(即跟覆盖的区别是基类中函数是否为虚函数)
情形3: 函数名相同、 函数参数不同、 分别位于派生类和基类中 -- 为 隐藏;(即与重载的区别是两个函数是否在同一个域(类)中)
小结:
首先:重载必须在同一个作用域当中讨论。覆盖和隐藏则是在基类和子类中。
其次:对于某个虚函数,如果子类参数相同,就是覆盖,否则就是隐藏。
最后:对于非虚函数而言,函数名相同就是为隐藏。
为了巩固知识点,可以做一下下面这道题:
class parent
{
public:
virtual void foo(){cout<<"foo from parent"<<endl;}
void foo1(){cout<<"foo1 from parent"<<endl;}
};
class son:public parent
{
public:
void foo(){cout<<"foo from son"<<endl;}
void foo1(){cout<<"foo1 from son"<<endl;}
};
int main()
{
parent *p=new son();
p->foo();
p->foo1();
system("pause");
return 0;
}
不知道你们的答案是什么,我第一次做的答案是:foo from son;foo1 from son
如果你放到VS当中去运行一下,得到的结果是:
运行结果
第一条输出没有问题,是一个虚函数的覆盖问题,考察的是动态绑定这个知识点,但是第二条输出就有两种解释:
对于输出foo1 from son,观点是,在son这个类中,我们对foo1这个函数进行了重写,这样的隐藏了parent类里的foo1,加上我们没有使用using声明式,使得parent::foo1()函数在son中可见,所以应该调用的是son::foo1()
对于输出foo1 from parent,观点是,非虚函数是静态绑定的,p的静态类型是parent,所以应该调用的是parent::foo1()
这就相互矛盾了。所以在实际编码过程中,绝对不要重新定义继承而来的非虚函数,不然你就是自己给自己找麻烦。至于出这道题的公司,我觉得应该下一次挑一个实战性选手:D
网友评论