老生常谈的话题了。。。。
某日逛论坛,见到有人发帖询问关于虚函数重载的问题,贴有代码询问问题所在。
仔细一看,一时之间竟说不出个所以然来,看来也是最近一心看java看太多了。
询问同事后,想起以前看过相关的知识,于是重新翻出书来看了一下,总算找会记忆。
所以在此记下。
重载(overload)
同一个作用域内定义同一名字的另一个函数,但是有着不同的参数个数或参数类型(不同的返回类型不算重载)
覆盖(override)
在派生类中定义一个与父类的某个非析够虚函数(当然,如果不是虚函数,就不会有运行时多态了)一模一样的函数,参数个数和类型以及返回值类型都要一样(返回值类型不同的是另一种情况)
隐藏(hide)
在内层作用域定义一个外层域的同名函数,这样将隐藏外层函数。这里,重新定义的函数参数个数、参数类型和返回类型都可以不一样。所以,如果派生类定义了一个父类虚函数的同名函数,且只是返回类型不同,则是隐藏了父类的函数,而不是重载。
接下来是有几个要注意的地方:
(1)重载解析只作用于静态类型。
也就是编译器在解析是否重载的时候会根据静态类型类查找相关函数。
也就是说,如下代码所示:
#include <iostream>
using namespace std;
class father
{
public:
virtual void test(float f_)
{
cout<<"father test"<<endl;
}
virtual ~father(){}
};
class child : public father
{
public:
virtual void test(int i_)
{
cout<<"child test"<<endl;
}
};
int main()
{
child tempChild;
father * pFather = &tempChild;
pFather->test(23); //调用的是father::test(float f_)
return 0;
}
(2)默认参数的问题。如果在覆盖的函数和被覆盖的函数所声明的默认参数值不同,则会出现问题了。正如上面所说的,重载的解析是根据静态类型的。而对于默认参数的解析也是一样。所以有可能出现调用了派生类函数(此时派生类参数和父类默认参数值不同)却使用父类默认参数的情况。
(3)如果想把被隐藏的函数引入到当前作用域,则可以使用using申明语句。如:using father::test()