
好的我们来详细讲解 C 中的运算符重载这是为自定义类型扩展运算能力的重要特性。核心概念运算符重载允许我们为自定义的类或结构体类型重新定义或赋予新的含义给 C 内置的运算符如,-,*,/,,等。其本质是定义了一个特殊的成员函数或友元函数。语法结构运算符重载函数通常具有以下形式之一成员函数形式返回类型 operator运算符(参数列表) { // 函数体 }对于双目运算符如,-,*,/参数列表通常包含一个参数表示右操作数左操作数则是调用该成员函数的对象本身通过this指针访问。友元函数或非成员函数形式返回类型 operator运算符(左操作数, 右操作数) { // 函数体 }对于双目运算符参数列表包含两个参数左操作数和右操作数。当运算符需要访问类的私有或保护成员时常将其声明为该类的friend。关键点可重载的运算符大部分 C 内置运算符都可以重载例如算术运算符 (,-,*,/,%)、关系运算符 (,!,,,,)、逻辑运算符 (,||,!)、赋值运算符 (,,-等)、下标运算符 ([])、函数调用运算符 (())、递增递减 (,--)、流运算符 (,)、指针相关运算符 (-,*,)等。不可重载的运算符.成员访问、.*成员指针访问、::作用域解析、?:条件运算符、sizeof以及typeid等运算符不能被重载。不能创建新的运算符。操作数限制运算符重载不能改变运算符的优先级和结合性。不能改变运算符操作数的个数例如重载必须有两个操作数。参数类型至少有一个操作数必须是用户定义的类型类或枚举。不能为内置类型重载运算符例如不能重载int int。const正确性对于不修改操作数的运算符如,应将其声明为const成员函数或使用const引用参数。示例复数类Complex#include iostream class Complex { private: double real; // 实部 double imag; // 虚部 public: Complex(double r 0.0, double i 0.0) : real(r), imag(i) {} // 成员函数形式重载加法运算符 Complex operator(const Complex rhs) const { return Complex(real rhs.real, imag rhs.imag); } // 成员函数形式重载减法运算符 - Complex operator-(const Complex rhs) const { return Complex(real - rhs.real, imag - rhs.imag); } // 成员函数形式重载乘法运算符 * (简化版不考虑复数乘法规则细节) Complex operator*(const Complex rhs) const { return Complex(real * rhs.real - imag * rhs.imag, real * rhs.imag imag * rhs.real); } // 成员函数形式重载前置自增运算符 Complex operator() { real; imag; return *this; // 返回修改后的自身引用 } // 成员函数形式重载后置自增运算符 (使用哑元int区分) Complex operator(int) { Complex temp *this; // 保存当前值 (*this); // 使用前置进行自增 return temp; // 返回自增前的值 } // 成员函数形式重载相等运算符 bool operator(const Complex rhs) const { return (real rhs.real) (imag rhs.imag); } // 成员函数形式重载不等于运算符 ! (通常基于实现) bool operator!(const Complex rhs) const { return !(*this rhs); } // 友元函数形式重载输出流运算符 (需要访问私有成员) friend std::ostream operator(std::ostream os, const Complex c); }; // 实现输出流运算符 std::ostream operator(std::ostream os, const Complex c) { os ( c.real c.imag i); return os; } int main() { Complex c1(3.0, 4.0); Complex c2(1.0, 2.0); Complex sum c1 c2; // 使用重载的 std::cout Sum: sum std::endl; // 使用重载的 Complex diff c1 - c2; std::cout Difference: diff std::endl; Complex product c1 * c2; std::cout Product: product std::endl; Complex c3 c1; std::cout c3 (pre-increment): c3 std::endl; // 前置 std::cout c3 now: c3 std::endl; Complex c4 c1; std::cout c4 (post-increment): c4 std::endl; // 后置 std::cout c4 now: c4 std::endl; if (c1 c2) { std::cout c1 equals c2 std::endl; } else { std::cout c1 not equals c2 std::endl; } return 0; }何时使用运算符重载提高代码可读性让自定义类型的使用方式更接近内置类型使代码更直观、自然。例如使用a b代替a.add(b)。数学或物理对象如向量、矩阵、复数、多项式等。容器类如使用[]访问元素使用输出内容。智能指针重载-和*模拟指针行为。注意事项避免滥用运算符重载应保持其直观含义。不要赋予运算符令人困惑或完全不同的意义例如用表示减法。保持一致性如果重载了通常也应该重载!重载了可能需要重载、、重载了可能需要考虑重载。性能考虑对于大型对象注意返回值和参数传递方式通常使用const引用避免拷贝考虑返回值优化 (RVO)。选择成员函数还是非成员函数赋值类运算符 (,,-等)、下标[]、成员访问-、自增自减、--通常作为成员函数。对称运算符如,,通常作为非成员函数常为友元以实现左操作数为内置类型时的转换如2 myComplex。流运算符和必须是友元非成员函数。通过合理使用运算符重载可以显著提升使用自定义类型的代码的清晰度和易用性。