1. 成员函数的概念
在面向对象编程中,成员函数是指与类相关联的函数,可以访问该类的所有成员变量和函数。成员函数可以在类的内部定义,在外部实现。
成员函数可以分为两种类型:
实例函数:依赖于类的对象进行调用。
静态函数:独立于类的对象进行调用,可以使用类名或者对象调用。
2. 成员函数的重载
重载是指在同一个作用域中定义多个同名的函数,但是这些函数的参数个数或者参数类型不同。函数的返回值和函数的访问修饰符不属于函数签名的一部分,所以这些参数相同但返回值或访问修饰符不同的情况并不能算作函数的重载。
成员函数可以重载,即在同一个类中定义多个同名的成员函数,只要它们的参数列表不同即可。成员函数的重载在使用对象调用成员函数时非常方便,可以根据传入的参数不同自动调用不同的函数。
以下代码演示了成员函数的重载:
class Calculator {
public:
int add(int a, int b) { return a + b; }
double add(double a, double b) { return a + b; }
};
int main() {
Calculator c;
std::cout << c.add(1, 2) << std::endl; // 输出 3
std::cout << c.add(1.0, 2.0) << std::endl; // 输出 3.0
return 0;
}
这里的Calculator类中定义了两个同名的add函数,它们的参数类型不同,因此可以根据传入的参数类型自动调用不同的函数。
3. 注意事项
3.1 成员函数的重载与默认参数
与普通函数不同,默认参数的设定不能影响函数重载,即不同的默认参数不能成为函数的重载。以下代码演示了这点:
class Calculator {
public:
int add(int a, int b, int c = 0) { return a + b + c; }
int add(int a, int b, int c = 1) { return a + b + c; }
};
int main() {
Calculator c;
std::cout << c.add(1, 2) << std::endl; // 编译错误
return 0;
}
这里的add函数在定义时都有一个默认参数c,而这个默认参数不同,应该可以当做两个不同的函数重载。但是编译会报错,提示函数冲突。
造成这个问题的原因在于,同一个函数名只能对应一个函数签名。虽然在计算参数列表的过程中,编译器可以根据缺省值推导出参数列表的实际长度,但由于默认参数只是在函数声明时指定的,对于成员函数而言,函数的实现是在类外面进行定义的。所以编译器在编译时只看到了两个完全相同的函数定义。
3.2 成员函数的重载与const关键字
成员函数可以使用const关键字修饰,用于定义常量成员函数。常量成员函数不能修改类的成员变量,即不能有写操作。我们可以对常量对象调用常量成员函数,但是不能对常量对象调用非常量成员函数。
成员函数的const关键字可以添加在函数声明和函数定义的两个位置,但是需要满足下面的两个条件:
在函数声明中使用const修饰的函数需要在函数定义中也要使用const修饰。
非静态成员函数可以使用const修饰符,而静态成员函数和构造函数不能使用const修饰符。
以下代码演示了成员函数的重载与const关键字:
class MyClass {
public:
void non_const_func() { // 非常量成员函数
std::cout << "Change member variable" << std::endl;
}
void non_const_func() const { // 常量成员函数
std::cout << "Read member variable" << std::endl;
}
};
int main() {
const MyClass obj1; // 常量对象
MyClass obj2; // 非常量对象
obj1.non_const_func(); // 输出 Read member variable
obj2.non_const_func(); // 输出 Change member variable
return 0;
}
这里的MyClass类中定义了两个同名的函数non_const_func,它们的一个是常量成员函数,一个是非常量成员函数。常量对象只能调用常量成员函数,而非常量对象可以调用两种成员函数。
4. 总结
成员函数是指与类相关联的函数,可以访问该类的所有成员变量和函数。成员函数可以分为实例函数和静态函数。成员函数可以重载,在同一个类中定义多个同名的成员函数,只要它们的参数列表不同即可。在使用对象调用成员函数时非常方便,可以根据传入的参数不同自动调用不同的函数。但是需要注意,函数重载不能使用默认参数,const关键字只能在非静态成员函数中使用。