前面我们学习了虚函数的相关概念,当父类和子类中都写了同样的函数,在调用的时候是调用的父类还是子类,这是经常会遇到的问题,本篇将会进行分析,并且总结一定的套路供以后使用,
1. C++中函数覆盖、重载、隐藏如何判断什么时候被使用?
实际使用过程中很少会出现几种类型一起出现的情况,因此作为不断理解及未来细品之用,总结起来,其调用规则检查按照:函数隐藏-->函数重载-->函数覆盖
2. 代码实例
#include <iostream>
class Base {
public:
virtual void Handle1(float x)
{
printf("Base::Handle1(float)");
}
void Handle1(int x)
{
printf("Base::Handle1(int)");
}
void Handle2(float x)
{
printf("Base::Handle2(float)");
}
void Handle3(float x)
{
printf("Base::Handle3(float)");
}
};
class Derived :public Base {
public:
//父类中已经声明为虚函数,子类中virtual可写可不写
//同名,参数返回值等一致,构成覆盖
virtual void Handle1(float x)
{
printf("Base::Handle1(float)");
}
//与父类函数的同名函数构成了函数隐藏
void Handle2(float x)
{
printf("Base::Handle2(float)");
}
//与父类函数的同名函数构成了函数隐藏
void Handle3(float x)
{
printf("Base::Handle3(float)");
}
//与子类中的同名函数构成函数重载,作用域、函数名、作用域相同
void Handle3(double x)
{
printf("Base::Handle3(double)");
}
};
/*
观察以上类声明及实现,试预测一下main中的执行结果。
注意两点:
1.调用的方法是哪个
2.调用造成的原因,是重载、覆盖、隐藏中的哪一种?
*/
int main(int argc, char* argv[])
{
Derived DervObj;
Base *pBase = &DervObj;//子类对象指针强转为父类指针
Derived *pDerv = &DervObj;//将子类变换为指针形式
Base BaseObj;
Base *pBase2 = &BaseObj;
//间接调用,本质指向的还是子类对象,查子类虚表,子类对象有函数覆盖,调用子类的Handle1
pBase->Handle1(3.14f);
//Handle1虚函数,pBase2为指针,间接调用:本质指向的是父类对象,查父类的虚表,调用父类Handle1
pBase2->Handle1(3.14f);
//虽然使用了指针有类域限制,直接调用:查找Base作用域中的Handle1,调用父类Handle1(函数重载)
//找到最佳匹配的函数
// (i)找到多个则提示二义性
// (ii)找不到则向该类域的上一层查找(父类)
// 一旦在某一个类域中找到该函数,则不会向上查找(函数隐藏规则)
pBase->Base::Handle1(3.14);
return 0;
}
3.学习视频地址:
函数覆盖、重载、隐藏的调用秘笈1
函数覆盖、重载、隐藏的调用秘笈2