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 重载条件 #

函数重载必须满足以下条件之一:

  1. 参数数量不同
  2. 参数类型不同
  3. 参数顺序不同(类型不同时)
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);

九、总结 #

重载要点 #

要点 说明
条件 参数列表不同
不能 仅返回值不同
解析 最佳匹配原则
优先级 精确匹配 > 类型提升 > 标准转换

最佳实践 #

  1. 重载函数应有相同语义
  2. 避免产生歧义
  3. 合理使用默认参数
  4. 注意作用域隐藏问题

下一步,让我们学习递归函数!

最后更新:2026-03-26