C++函数重载 #
一、函数重载概述 #
函数重载允许定义多个同名函数,但参数列表不同。
1.1 为什么需要重载 #
cpp
// 没有重载:需要不同的函数名
int addInt(int a, int b);
double addDouble(double a, double b);
int addThreeInt(int a, int b, int c);
// 有重载:使用相同的函数名
int add(int a, int b);
double add(double a, double b);
int add(int a, int b, int c);
1.2 重载条件 #
函数重载必须满足以下条件之一:
- 参数数量不同
- 参数类型不同
- 参数顺序不同(类型不同时)
cpp
// 参数数量不同
void func(int a);
void func(int a, int b);
// 参数类型不同
void func(int a);
void func(double a);
// 参数顺序不同
void func(int a, double b);
void func(double a, int b);
二、重载规则 #
2.1 不能仅通过返回值区分 #
cpp
// 错误:仅返回值不同
int func();
double func(); // 编译错误
2.2 typedef不产生新类型 #
cpp
typedef int Integer;
void func(int x);
void func(Integer x); // 错误:与上一个函数相同
2.3 const在参数中的影响 #
cpp
// 值传递:顶层const不影响
void func(int x);
void func(const int x); // 错误:重复定义
// 指针传递:底层const有影响
void func(int* ptr);
void func(const int* ptr); // 正确:不同类型
// 引用传递:const有影响
void func(int& ref);
void func(const int& ref); // 正确:不同类型
2.4 默认参数与重载 #
cpp
void func(int a);
void func(int a, int b = 10);
// 调用时可能产生歧义
func(5); // 错误:调用哪个?
三、重载解析 #
3.1 最佳匹配 #
编译器选择最匹配的函数:
cpp
void func(int x);
void func(double x);
void func(long x);
int main() {
func(10); // 调用func(int),精确匹配
func(3.14); // 调用func(double),精确匹配
func(10L); // 调用func(long),精确匹配
func('A'); // 调用func(int),char提升为int
func(10u); // 调用func(int),unsigned int转换
return 0;
}
3.2 匹配等级 #
cpp
void func(int x);
void func(double x);
int main() {
// 1. 精确匹配
func(10); // func(int)
func(3.14); // func(double)
// 2. 类型提升
func('A'); // char -> int,调用func(int)
func(3.14f); // float -> double,调用func(double)
// 3. 标准转换
func(10L); // long -> int 或 long -> double
// 两者都是标准转换,可能产生歧义
return 0;
}
3.3 歧义情况 #
cpp
void func(long x);
void func(float x);
int main() {
func(10); // 错误:int可以转换为long或float,产生歧义
return 0;
}
// 解决方法
void func(int x); // 添加精确匹配版本
四、常见重载示例 #
4.1 数学运算 #
cpp
int abs(int x) {
return x < 0 ? -x : x;
}
double abs(double x) {
return x < 0 ? -x : x;
}
long abs(long x) {
return x < 0 ? -x : x;
}
4.2 打印函数 #
cpp
void print(int x) {
std::cout << "int: " << x << std::endl;
}
void print(double x) {
std::cout << "double: " << x << std::endl;
}
void print(const std::string& x) {
std::cout << "string: " << x << std::endl;
}
void print(const char* x) {
std::cout << "c-string: " << x << std::endl;
}
4.3 数组处理 #
cpp
// 处理int数组
int sum(const int* arr, size_t size);
// 处理double数组
double sum(const double* arr, size_t size);
// 处理vector
int sum(const std::vector<int>& vec);
double sum(const std::vector<double>& vec);
4.4 构造函数重载 #
cpp
class Date {
private:
int year, month, day;
public:
// 默认构造
Date() : year(1970), month(1), day(1) {}
// 年月日构造
Date(int y, int m, int d) : year(y), month(m), day(d) {}
// 字符串构造
Date(const std::string& dateStr) {
// 解析字符串
}
// 拷贝构造
Date(const Date& other) = default;
};
五、运算符重载 #
5.1 基本概念 #
运算符重载是特殊的函数重载。
cpp
class Complex {
public:
double real, imag;
Complex(double r = 0, double i = 0) : real(r), imag(i) {}
// 重载 + 运算符
Complex operator+(const Complex& other) const {
return Complex(real + other.real, imag + other.imag);
}
// 重载 - 运算符
Complex operator-(const Complex& other) const {
return Complex(real - other.real, imag - other.imag);
}
};
int main() {
Complex a(1, 2);
Complex b(3, 4);
Complex c = a + b; // 调用 operator+
return 0;
}
5.2 可重载的运算符 #
cpp
// 算术运算符:+ - * / % ^ & | ~
// 比较运算符:== != < > <= <=>
// 逻辑运算符:&& || !
// 位运算符:& | ^ ~ << >>
// 赋值运算符:= += -= *= /= 等
// 其他:() [] -> , ->*
5.3 不可重载的运算符 #
cpp
// :: 作用域解析
// . 成员访问
// .* 成员指针访问
// ?: 三元运算符
// sizeof 大小运算符
// typeid 类型信息
六、函数重载与作用域 #
6.1 局部作用域 #
cpp
void func(int x);
int main() {
void func(double x); // 局部声明隐藏全局func
func(10); // 调用func(double)
func(3.14); // 调用func(double)
return 0;
}
6.2 类作用域 #
cpp
class Base {
public:
void func(int x);
};
class Derived : public Base {
public:
void func(double x); // 隐藏Base::func(int)
// 使用using引入基类函数
using Base::func;
};
int main() {
Derived d;
d.func(10); // 调用Base::func(int)
d.func(3.14); // 调用Derived::func(double)
return 0;
}
七、重载与模板 #
7.1 函数模板与重载 #
cpp
// 函数模板
template<typename T>
T add(T a, T b) {
return a + b;
}
// 模板特化
template<>
std::string add<std::string>(std::string a, std::string b) {
return a + " " + b;
}
// 非模板重载
int add(int a, int b, int c) {
return a + b + c;
}
int main() {
std::cout << add(1, 2) << std::endl; // 模板
std::cout << add(1.5, 2.5) << std::endl; // 模板
std::cout << add(1, 2, 3) << std::endl; // 非模板
return 0;
}
7.2 重载解析优先级 #
cpp
template<typename T>
void func(T x);
void func(int x);
int main() {
func(10); // 调用非模板版本(优先)
func(10.0); // 调用模板版本
return 0;
}
// 优先级:
// 1. 精确匹配的非模板函数
// 2. 精确匹配的模板特化
// 3. 模板实例化
// 4. 类型转换后的非模板函数
八、最佳实践 #
8.1 重载应该有相同语义 #
cpp
// 好的重载:语义一致
int size(const std::vector<int>& vec);
int size(const std::string& str);
int size(const char* str);
// 不好的重载:语义不一致
void process(int x); // 打印x
void process(double x); // 计算平方
8.2 避免歧义 #
cpp
// 可能产生歧义
void func(long x);
void func(float x);
// 解决:添加精确匹配
void func(int x);
8.3 使用默认参数代替简单重载 #
cpp
// 不推荐
void func();
void func(int a);
// 推荐
void func(int a = 0);
九、总结 #
重载要点 #
| 要点 | 说明 |
|---|---|
| 条件 | 参数列表不同 |
| 不能 | 仅返回值不同 |
| 解析 | 最佳匹配原则 |
| 优先级 | 精确匹配 > 类型提升 > 标准转换 |
最佳实践 #
- 重载函数应有相同语义
- 避免产生歧义
- 合理使用默认参数
- 注意作用域隐藏问题
下一步,让我们学习递归函数!
最后更新:2026-03-26