17、函数重载
函数重载是C++
的一项重要特性,通过函数重载,可以在同一个作用域内定义多个同名函数,但这些函数的参数列表必须不同(参数类型、参数个数或参数顺序不同)。
函数重载的规则
- 函数名相同: 重载的函数必须使用相同的函数名。
- 参数列表不同: 重载的函数必须有不同的参数列表,包括参数类型、参数个数或参数顺序。
- 返回值类型不影响重载: 仅返回值类型不同,不能构成函数重载。
函数重载的解析
当调用一个重载函数时,编译器会根据实际传递的参数类型、个数和顺序,选择最匹配的函数版本进行调用,如果找不到最匹配的,编译器会认为有歧义,报错。
示例代码:
#include <iostream>
using namespace std;
// 1. 参数个数不同
void print(int a) {
cout << "Printing an integer: " << a << endl;
}
void print(int a, int b) {
cout << "Printing two integers: " << a << ", " << b << endl;
}
// 2. 参数类型不同
void print(double a) {
cout << "Printing a double: " << a << endl;
}
void print(const string& str) {
cout << "Printing a string: " << str << endl;
}
// 3. 参数顺序不同
void print(int a, double b) {
cout << "Printing an integer and a double: " << a << ", " << b << endl;
}
void print(double a, int b) {
cout << "Printing a double and an integer: " << a << ", " << b << endl;
}
int main() {
print(10); // 调用 void print(int a)
print(10, 20); // 调用 void print(int a, int b)
print(3.14); // 调用 void print(double a)
print("Hello"); // 调用 void print(const string& str)
print(10, 3.14); // 调用 void print(int a, double b)
print(3.14, 10); // 调用 void print(double a, int b)
return 0;
}
进阶知识点
运算符重载: 运算符重载本质上也是函数重载,它允许为用户自定义类型定义运算符的行为。
在C++
中,参数类型是否 const
不会产生函数重载。这是因为 const
修饰符作用于参数时,只是限制了函数内部对参数值的修改,而不会改变参数的类型本身。
因此,以下两个函数声明会被认为是重复定义,而不是重载:
void func(int a); // 1
void func(const int a); // 2: 错误,重复定义,不是重载
编译器会将上述两个函数视为完全相同的函数签名,因此会导致编译错误。
const
修饰值参数
对于值传递的参数(如 int a
),const
只是限制函数内部不能修改参数的值,但不会影响函数的外部行为。因此,以下两个函数声明是等价的:
void func(int a); // 1
void func(const int a); // 2: 与 1 等价
编译器会将它们视为相同的函数签名,因此无法重载。
const
修饰指针或引用参数
对于指针或引用参数,const
的位置不同会产生不同的语义,因此可以形成重载:
const
修饰指针指向的内容:void func(int* p); // 1: 接受普通指针 void func(const int* p); // 2: 接受指向常量的指针
这两个函数可以重载,因为参数类型不同(
int*
和const int*
)。
const
修饰引用:void func(int& r); // 1: 接受普通引用 void func(const int& r); // 2: 接受常量引用
这两个函数也可以重载,因为参数类型不同(
int&
和const int&
)。
const
修饰成员函数
对于类的成员函数,const
修饰的是成员函数本身,而不是参数。这种 const
会影响函数签名,因此可以形成重载:
class MyClass {
public:
void func() { std::cout << "Non-const func\n"; } // 1
void func() const { std::cout << "Const func\n"; } // 2
};
这里,func()
和 func() const
是两个不同的函数,可以重载。调用时,编译器会根据对象的 const
属性选择正确的版本:
MyClass obj;
const MyClass constObj;
obj.func(); // 调用 void func()
constObj.func(); // 调用 void func() const
练习
编写一个程序,定义三个重载函数
max()
,分别用于求两个整数、两个浮点数和三个整数中的最大值。编写一个程序,定义一个函数模板
swap()
,用于交换两个变量的值,并使用该模板交换两个整数、两个浮点数和两个字符串的值。编写一个程序,定义一个类
Point
,表示二维平面上的点,并重载+
运算符,实现两个点的加法运算。以下代码是否能编译通过?如果不能,为什么?
void func(int a); void func(const int a);
编写一个程序,定义一个函数
print
,使其能够重载以下调用:print(int* p)
print(const int* p)
print(int& r)
print(const int& r)
定义一个类
String
,并重载operator[]
,使其支持以下调用:char& operator[](int index);
const char& operator[](int index) const;
