在 C++ 中,重载(Overloading) 是指允许同名的函数或运算符有不同的实现,编译器会根据参数或操作数的差异自动选择对应的版本。重载分为函数重载运算符重载,核心目的是提高代码的可读性和灵活性。

一、函数重载

函数重载指在同一作用域内,声明多个同名函数,但它们的参数列表(参数类型、个数或顺序)不同。编译器会根据调用时的实参自动匹配对应的函数。

1.函数重载的条件

  • 函数名必须相同。
  • 参数列表必须不同(至少满足以下一项):
    • 参数个数不同;
    • 参数类型不同;
    • 参数顺序不同(仅当类型不同时有效)。
  • 返回值类型不同不能作为函数重载的条件(因为调用时无法仅通过返回值区分)。

2.示例:函数重载

#include <iostream>
using namespace std;

// 1. 两个int相加
int add(int a, int b) {
cout << "int + int: ";
return a + b;
}

// 2. 两个double相加(参数类型不同,构成重载)
double add(double a, double b) {
cout << "double + double: ";
return a + b;
}

// 3. 三个int相加(参数个数不同,构成重载)
int add(int a, int b, int c) {
cout << "int + int + int: ";
return a + b + c;
}

// 4. int和double相加(参数顺序不同,构成重载)
double add(int a, double b) {
cout << "int + double: ";
return a + b;
}

int main() {
cout << add(2, 3) << endl; // 调用1:输出 5
cout << add(2.5, 3.5) << endl; // 调用2:输出 6
cout << add(1, 2, 3) << endl; // 调用3:输出 6
cout << add(2, 3.5) << endl; // 调用4:输出 5.5
return 0;
}

3.函数重载的作用

  • 避免为相似功能的函数起不同名字(如 addIntaddDouble),提高代码可读性。
  • 让函数调用更自然(如用 add 统一表示“相加”操作,无论参数类型如何)。

二、运算符重载

运算符重载指赋予已有运算符新的含义,使它能用于自定义类型(如类对象)的操作。例如,让两个 Point 类对象可以用 + 相加,或用 << 输出。

1.运算符重载的语法
通过定义运算符重载函数实现,语法为:

返回值类型 operator运算符(参数列表) {
// 运算符的实现逻辑
}

运算符重载函数可以是类的成员函数,也可以是友元函数(根据运算符的使用场景选择)。

2.示例1:成员函数重载运算符(以 + 为例)
假设我们有一个 Point 类,表示二维坐标,希望实现 p1 + p2 得到新的坐标点(x1+x2, y1+y2):

class Point {
private:
int x, y;
public:
Point(int x=0, int y=0) : x(x), y(y) {}

// 成员函数重载 + 运算符(参数为另一个Point对象)
Point operator+(const Point& other) const {
// 返回新的Point对象,x和y分别相加
return Point(x + other.x, y + other.y);
}

// 用于输出的成员函数
void print() const {
cout << "(" << x << ", " << y << ")" << endl;
}
};

int main() {
Point p1(1, 2), p2(3, 4);
Point p3 = p1 + p2; // 等价于 p1.operator+(p2)
p3.print(); // 输出 (4, 6)
return 0;
}

3.示例2:友元函数重载运算符(以 << 为例)
<< 是输出运算符,若要直接用 cout << p 输出 Point 对象,需将其重载为友元函数(因为左操作数是 cout,不是 Point 对象,无法作为成员函数实现):

#include <iostream>
using namespace std;

class Point {
private:
int x, y;
public:
Point(int x=0, int y=0) : x(x), y(y) {}

// 声明友元函数:重载 << 运算符
friend ostream& operator<<(ostream& os, const Point& p);
};

// 友元函数实现:cout << p 时调用
ostream& operator<<(ostream& os, const Point& p) {
os << "(" << p.x << ", " << p.y << ")"; // 访问私有成员x、y
return os; // 支持链式输出(如 cout << p1 << p2)
}

int main() {
Point p(1, 2);
cout << "Point: " << p << endl; // 等价于 operator<<(cout, p)
// 输出:Point: (1, 2)
return 0;
}

4.运算符重载的限制

  • 不能重载的运算符:.(成员访问)、.*(成员指针访问)、::(作用域解析)、? :(三目运算符)、sizeof(长度计算)。
  • 重载后运算符的优先级、结合性、操作数个数不能改变(例如 + 仍为双目运算符)。
  • 必须有一个操作数是自定义类型(不能重载内置类型的运算符,如 int + int)。