关于C++重载、重写、重定义的理解
三个名词的定义
重载:(overload)是指同一可访问区内被声明的几个具有不同参数列(参数的类型,个数,顺序不同)的同名函数,根据参数列表确定调用哪个函数,重载不关心函数返回类型,即返回类型可以相同或不同。
重写(覆盖):(override)是指派生类中存在重新定义的函数。其函数名,参数列表,返回值类型,所有都必须同基类中被重写的函数一致。只有函数体不同(花括号内),派生类调用时会调用派生类的重写函数,不会调用被重写函数。重写的基类中被重写的函数必须有virtual修饰。
重载和重写的区别:
(1)范围区别:重写和被重写的函数在不同的类中,重载和被重载的函数在同一类中。
(2)参数区别:重写与被重写的函数参数列表一定相同,重载和被重载的函数参数列表一定不同。
(3)virtual的区别:重写的基类必须要有virtual修饰,重载函数和被重载函数可以被virtual修饰,也可以没有。
隐藏和重写,重载的区别:
(1)与重载范围不同:隐藏函数和被隐藏函数在不同类中。
(2)参数的区别:隐藏函数和被隐藏函数参数列表可以相同,也可以不同,但函数名一定同;当参数不同时,无论基类中的函数是否被virtual修饰,基类函数都是被隐藏,而不是被重写。
正常情况下的重载
class A{
public:
void test(int i);
void test(double i); //overload
void test(int i, double j); //overload
void test(double i, int j); //overload
int test(int i); //错误,非重载。注意重载不关心函数返回类型。
};
之前说到重载的三个条件,类型、顺序或个数不相同,只要满足一个就可以说是重载吗?显然,类型或个数不同时肯定可以算是重载的,下面考虑仅顺序不同的情况。
class A{
public:
void test(int a, int b);
void test(int b, int a); //不是重载
};
test(int a, int b)和test(int b, int a)仅顺序不同,但是参数类型相同,这不能算做重载,实验如下:
#include <iostream>
using namespace std;
class A{
public:
void test(int a, int b)
{
cout << a+b << endl;
cout << "test(int a, int b)" << endl;
}
void test(int b, int a) //不是重载
{
cout << a+b << endl;
cout << "test(int b, int a)" << endl;
}
};
int main() {
cout << "hello world" << endl;
return 0;
}
运行结果,编译无法通过。
/code/main.cpp:12:8: error: ‘void A::test(int, int)’ cannot be overloaded
void test(int b, int a) //不是重载
^
/code/main.cpp:7:8: error: with ‘void A::test(int, int)’
void test(int a, int b)
总的来说,辨别是否是重载函数,在于两个同名函数是否能通过参数进行区分,或者说是否能唯一辨识,避免出现二义性。