函数的常量性不同可以重载;参数为引用时常量性不同可以重载;指针所指对象的常量性不同可以重载;只有传值参数以及指针本身的常量性不同时是不可以重载的。
以下情况,仅常量性不同的重载是合法的。
//成员函数的常量性不同,可以重载
class C {
public:
void FuncA(int i);
void FuncA(int i) const;
};
//参数类型为引用时,常量性不同可以重载
void FuncB(int& i);
void FuncB(const int& i);
//指针所指对象的常量性不同,可以重载
void FuncC(int *p);
void FuncC(const int *p);
成员函数的常量性可以认为是指针所指对象的常量性,当成员函数为const类型则说明调用该方法的类实例为const,相当于this指针为指向常量的指针。总结下来,引用和指针所指对象的常量性不同可以重载。(有些人将引用理解为指向对象的常量指针,这样一来剩下两种情况还可以进一步理解为:只有指针所指对象的常量性不同时可以重载。)
以下情况,仅常量性不同不可以重载。
//传值调用形参常量性不同,不可以重载
void FuncD(int i);
void FuncD(const int i);
//指针本身的常量性不同,不可以重载
void FuncE(int *p);
void FuncE(int * const p);
实际上以上两种情况也可以归为一种。当我们使用传址调用(传指针)时,可以被看做是传递指针值的传值调用,指针自身的常量性不同不能重载。总结来看即为:非引用类型的参数本身的常量性不同不能重载。
那么,为什么非引用类型参数的常量性不同不能重载呢?C++的这样设计的道理何在?这还得从C语言说起,C++出于与C语言保持兼容的考虑,保留了C语言中的传值调用(参考Python、Java这些面向对象语言,他们根本没有这个概念,从C++的角度来看它们的函数调用都是引用传参)。而在传值调用过程中,由于函数内部总会在执行函数体之前复制一个实参副本,并在函数体内使用副本参与运算。这就导致实参本身(实参为指针时,指针所指对象就不一定不改变了。)在函数内部永远不会改变,函数返回时实参的值总是调用时实参的值。既然如此,那么实参是否为const类型根本无关紧要,即使不是const类型函数返回时也一定不会变。
相反地,引用和指针所指对象的常量性则显得很重要了!因为这些对象在函数内部是有可能被改变的。
总而言之,判断一组同名函数能否构成重载,要看能不能通过修改形参来影响实参的值,如果两个函数实参的值都能被修改或都不能被修改,则不能构成重载;否则构成重载。