重载(overload):是指编写一个与已知函数同名但是参数表不同的函数。重载主要属于静态编联范畴,是在编译期就完成地址的分配。
普通成员函数的重载主要分成三部分:
(1)在一个类中说明重载。
如 show(int a,char b);//在编译期经过编译器修饰后函数名会变成int_char_show
show(char* c,double d);//在编译期经过编译器修饰后函数名会变成char_double_show
(2)在基类中声明一个函数,在子类中重载这个函数(未声明virtual关键字)(还有一种说法是隐藏,但我认为可以简单的认为是一种特殊的重载更确切,不考虑这个两个函数具有相同的参数),经过编译期之后,有三种编译区分的方法:
1.根据参数特征进行区分。
如 Base: show(int ,int );
Derived: show(int ,float);
这两个函数不是一个函数,编译器可以区分
2.根据“::”作用域符进行区分。编译器进行编译时,可根据不同的作用域进行区分重载函数。
如 Base::show( );
Derived::show( );
3.根据类对象进行区分调用哪一个重载函数。
如 Base b; b.show( );
Derived d; d.show( );
由上可知,重载只是一种语言特性,与多态无关,与面向对象无关。
覆盖(override):是指派生类重写基类的虚函数,重写的函数必须具有一致的参数表和返回值。覆盖是一种动态编联。在运行期进行确定所调用的函数地址。
覆盖是与多态密切相关的一种机制,与面向对象有关。
以下通过一个程序来说明重载与覆盖:
#include<iostream>
using namespace std;
class A
{
public:
A(int data = 0):m_data(data){}
virtual int doGetData()
{
return m_data;
}
int GetData()
{
return doGetData();
}
private:
int m_data;
};
class B:public A
{
public:
B(int data = 1):m_data(data){}
int doGetData()
{
return m_data;
}
private:
int m_data;
};
class C:public B
{
public:
C(int data=2):m_data(data){}
private:
int m_data;
};
int main(int argc, char* argv[])
{
C c(10);
cout<<c.GetData()<<endl;
cout<<c.A::GetData()<<endl;
cout<<c.B::doGetData()<<endl;//结果为1,理由同上。
cout<<c.C::GetData()<<endl;//结果为1 ,理由同上。
cout<<c.doGetData()<<endl;//由于C类中未定义虚函数doGetData()的接口,所以会调用父类的接口。结果为1.
cout<<c.A::doGetData()<<endl;//c.A::doGetData(),C类对象会直接调用A类的作用域内的内存空间,直接调用A的doGetData(),结果为0.
cout<<c.C::doGetData()<<endl;//因为C类为重定义该接口,所以调用B类的doGetd(),而B类的doGetData()返回B::m_data,故输出为1.
return 0;
}