C++ 重载运算符和重载函数

在 C++ 中,“重载”是一种让同一名称对应多种行为的机制,主要分为函数重载(Function Overloading)和运算符重载(Operator Overloading)。它们都基于编译时的“重载决议”(overload resolution),根据参数类型、数目等来选择最合适的版本。


一、函数重载

  1. 概念
    在同一作用域中,可以声明多个同名函数,它们的参数列表(参数个数或类型顺序)必须不同,返回类型不计入重载决议。
  2. 语法示例// 同名不同签名 void print(int x); void print(double x); void print(const std::string& s, bool newline = true);
  3. 调用决议
    • 编译器根据实参类型选最佳匹配(exact, promotion, standard conversion, user-defined conversion)。
    • 若匹配歧义或无合适重载,则编译错误。
  4. 注意事项
    • 默认参数可能导致冲突:void f(int x, int y = 0); void f(int x); // 与上面冲突
    • 模板函数也可与普通函数一起参与匹配,模板是一等公民:template<typename T> void swap(T& a, T& b); void swap(int* a, int* b); // 专门化版本

二、运算符重载

  1. 目的
    让自定义类型(类/结构体)能使用内建运算符(+ - * / [] () 等)表达直观的操作。
  2. 成员函数 vs. 非成员函数
    • 成员形式返回值 operatorX(参数…)struct Vec { double x, y; Vec operator+(const Vec& rhs) const { return { x + rhs.x, y + rhs.y }; } };
      • 一元运算符(如 -v)参数列表为空;二元如 v1 + v2,右侧为参数 rhs,左侧是 *this
    • 非成员形式(通常配合友元)struct Vec { double x, y; friend Vec operator*(double s, const Vec& v) { return { v.x * s, v.y * s }; } };
  3. 常见运算符
    • 算术运算+ - * / %
    • 赋值与复合赋值=+=, -=, *= …
    • 比较运算==, !=, <, >, <=, >=
    • 下标、函数调用、流插入operator[]operator()operator<</>>
    • 递增/递减、一元正负++, --, +-, !
  4. 返回值建议
    • 对于 a + b 返回新对象;对 a += b 返回 *this &,以支持链式调用:Vec& operator+=(const Vec& rhs) { x += rhs.x; y += rhs.y; return *this; }
  5. 注意事项
    • 不可新定义运算符优先级和结合性。
    • 切勿滥用:有时明确命名(如 add()equals())更易读。
    • 保持行为一致性:a == b 应与 !(a < b) && !(b < a) 等价。

三、最佳实践

  • 清晰、直观:只有当运算符意义明确、与内建类型行为一致时才重载。
  • 尽量配对:若重载 <,最好也重载 ><=>= 或使用 <=>(C++20 三路比较)。
  • 异常安全:在运算中抛出异常时保证对象状态不崩溃。
  • 文档说明:为重载行为写注释,避免使用者误解。

通过函数重载和运算符重载,C++ 为库设计者提供了强大而灵活的接口定制能力,但同时也需谨慎使用,以保持代码的可读性和一致性。

类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注