在编程中我们经常使用C++中的重载、覆盖、隐藏,那么在这里简单总结下他们之间的区别。
一. 重载
重载应该是这三个中最容易理解的,其本身是面向过程中的语言特性,是不具备多态性的,只是同名函数不同返回值或者不同参数的函数。这里对重载不做多余的赘述。一般在c++中常见的是重载拷贝构造函数,重载构造函数,重载赋值运算符等等。
二. 覆盖
覆盖是面向对象中的一种特性,是多态性的具体实现,根据代码实例来理解覆盖是如何体现面向对象中的多态性的:
定义一个基类Base
class Base
{
public:
Base();
virtual ~Base();
virtual void Cover();
};
Base::Base()
{
}
Base::~Base()
{
}
void Base::Cover()
{
printf("Cover --- This is Base Class!\n");
}
Base的子类ChildA
class ChildA : public Base
{
public:
ChildA();
~ChildA();
void Cover();
};
ChildA::ChildA()
{
}
ChildA::~ChildA()
{
}
void ChildA::Cover()
{
printf("Cover --- This is Child A! \n");
}
main.cpp:
int main()
{
Base* A = new Base();
Base* B = new ChildA();
A->Cover();
B->Cover();
ChildA* C = new ChildA();
Base* D = static_cast<Base*>(C);
C->Cover();
D->Cover();
getchar();
delete A;
delete B;
delete C;
return 0;}
以上输出结果如下:
![]()
从以上可以看出来new操作符后面的类才是真正的对象本身,childA通过虚函数Cover()的实现对基类的Cover进行了覆盖操作,也就是child派生类向上静态转换为Base,调用Cover函数,最终也是调用的子类的方法。这就是派生类的方法对基类的方法的覆盖,也是is-a的思想。
三. 隐藏
相对于覆盖,隐藏其实是子类与基类的方法同名(形参、返回值都相同,并非重载),即子类对基类的非虚函数进行了重新定义。当我们用派生类调用同名函数时,此时调用的是子类的方法。但是转换到基类后,再次调用该方法,就是基类的方法了。
对以上基类和子类添加如下的方法:
void Base::Hide()
{
printf("Hide --- This is Base Class!\n");
}
void ChildA::Hide()
{
printf("Hide --- This is Child A! \n");
}
main.cpp
int main()
{
Base* A = new Base();
Base* B = new ChildA();
A->Hide();
B->Hide();
ChildA* C = new ChildA();
Base* D = static_cast<Base*>(C);
C->Hide();
D->Hide();
getchar();
delete A;
delete B;
delete C;
return 0;
}
打印结果:
由以上可以看出来子类对象调用Hide方法时,调用的是自己的Hide方法,并未调用基类的Hide,这就是子类隐藏了基类的同名方法。
我们还可以看到当new出子类对象后,当该对象的类型名是子类类型名时,进行显示静态转换为基类对象后,再次调用Hide方法时,这时候调用的就是基类的方法。因为该方法并非虚函数,没有被子类覆盖,基类不可能通过虚函数表找到子类的实现。
以上就是对重载、覆盖、隐藏的简单理解。