C++ 重载、覆盖、隐藏

 

重载、覆盖和隐藏是C++中容易混淆的概念,作为C++研发人员有必要了解其区别和实现,以下结合概念和源码加以说明。

 

1、重载

重载指同一个类或者范围内,被声明的同名函数其参数数量或者类型不同,使用时根据函数参数列表确定调用哪个函数,需要注意的是重载不关注函数返回类型。

其特点:1)相同范围,2)函数名称相同,3)参数不同(类型或数量),4)virtual可有可无

代码:

#include <iostream>
using namespace std;
class A
{
public:
void fun(){ cout<<"(void)"<<endl;}
int fun(int a){ cout<<"(int)a:"<<a<<endl;}
void fun(const char *str){cout<<"(char*)str:"<<str<<endl;}
//int fun(int b){ cout<<"(int)b"<<b<<endl;}//报错,重载不关注返回类型
};
int main(int argc, char const *argv[])
{
A a;
a.fun();
a.fun(1);
a.fun("string");
return 0;
}
/* 输出:
(void)
(int)a:1
(char*)str:string
*/

 

2、覆盖

覆盖/重写指派生类的成员函数覆盖基类中同名函数,即当在子类中定义了一个与父类完全相同的虚函数时,则称子类的这个函数重写(也称覆盖)了父类的这个虚函数。

特点:1)基类中被重写的函数必须为虚函数,2)重写在不同范围(基类和派生类),3)函数名和对应参数必须相同。

代码:

#include <iostream>
using namespace std;
class A
{
public:
virtual void fun1(){cout<<"A fun1"<<endl;}
virtual void fun2(){cout<<"A fun2"<<endl;}
void fun3(){cout<<"A fun3"<<endl;}
};
class B:public A
{
public:
void fun1(){cout<<"B fun1"<<endl;}
void fun3(){cout<<"B fun3"<<endl;}
};
class C:public B
{
public:
void fun2(){cout<<"C fun2"<<endl;}
};

int main(int argc, char const *argv[])
{
A *pA = new C;
pA->fun1();
pA->fun2();
pA->fun3();
B *pB = new C;
pB->fun1();
pB->fun2();
pB->fun3();
return 0;
}
/* 输出:
B fun1 //继承B的fun1,B重写A的fun1
C fun2 //重写B的fun2
A fun3
B fun1
C fun2 //重写B的fun2
B fun3
*/

 

3、隐藏

隐藏/重定义指派生类函数屏蔽基类中的同名函数,函数名称相同,不能构成覆盖的都视作为隐藏。

特点:1)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字,此时基类的函数被隐藏;2)如果派生类的函数与基类的函数同名,但是参数不同,此时,不论有无virtual关键字,基类的函数将被隐藏。

代码:

#include <iostream>
using namespace std;
class A
{
public:
void fun(int x){cout<<x<<endl;}
};
class B1:public A
{
public:
void fun(const char *x){cout<<x<<endl;}
//void fun(int x); has been hided
};
class B2:public A
{
public:
void fun(const char *x){cout<<x<<endl;}
void fun(int x){A::fun(x);}
};

class A1
{
public:
virtual fun(int x){cout<<x<<endl;}
};
class C:public A1
{
public:
void fun(const char *x){cout<<x<<endl;}//此处隐藏导致fun(int)无法访问
};
int main(int argc, char const *argv[])
{
B1 *pB1 = new B1;
pB1->fun("Hello B1");
//pB1->fun(1);//error: invalid conversion from 'int' to 'const char*'
B2 *pB2 = new B2;
pB2->fun("Hello B2");
pB2->fun(22);

C *pC = new C;
pC->fun("Hello C");
//pC->fun(33);//error: invalid conversion from 'int' to 'const char*'
return 0;
}
/* 输出
Hello B1
Hello B2
22 //由于隐藏B1/2不能调用fun(int),可通过在B2中重载使用该函数
Hello C
*/