c++如何实现运算符重载_c++ operator重载规则【实战】

7次阅读

C++中sizeof、?:、::、.、.*五个运算符完全禁止重载;=、[]、()、->只能作为类的非静态成员函数重载

c++如何实现运算符重载_c++ operator重载规则【实战】

哪些运算符能重载、哪些不能

不是所有运算符都能重载:sizeof?:(三目)、::作用域)、.(成员访问)、.*指针到成员)这五个完全禁止重载。其余大部分可以,但有隐含限制:比如 =[]()-> 只能作为类的非静态成员函数重载,不能是全局函数;而 +== 这类则既可成员也可友元(推荐友元,尤其对流操作符)。

常见误用是试图重载 . 来实现“透明代理”,结果编译报错 Error: 'operator.' must be a non-Static member function —— 实际上 c++ 不允许这么做,得改用 -> 配合智能指针或代理类模式绕过。

为什么 operator 必须用友元函数

因为左操作数是 std::ostream&(如 std::cout),它不属于你的类,你没法给 std::ostream 添加成员函数。所以必须写成全局函数,再用 friend 打开类的私有访问权限:

class Vec {     int x_, y_; public:     Vec(int x, int y) : x_(x), y_(y) {}     friend std::ostream& operator<<(std::ostream& os, const Vec& v) {         return os << "(" << v.x_ << ", " << v.y_ << ")";     } };

漏掉 friend 会导致编译错误 error: 'x_' is private within this context;不加 const Vec& 引用参数,则临时对象无法绑定,出现 error: binding reference to a temporary

立即学习C++免费学习笔记(深入)”;

赋值运算符 operator= 的深拷贝陷阱

默认生成的 operator= 是浅拷贝,遇到含裸指针的类会引发双重释放或悬空指针。手动重载时必须做三件事:

  • 自赋值检查:if (this == &other) return *this;
  • 释放当前资源(如有)
  • 深拷贝新资源,并返回 *this

更安全的做法是用“拷贝-交换”惯用法(copy-and-swap):

Vec& operator=(Vec other) { // 注意:传值,自动调用拷贝构造     swap(*this, other);     return *this; } friend void swap(Vec& a, Vec& b) noexcept {     using std::swap;     swap(a.x_, b.x_);     swap(a.y_, b.y_); }

这样天然规避自赋值问题,也保证异常安全。但注意:如果类里有大对象(如 std::vector),传值成本高,此时仍建议传统写法 + 显式深拷贝。

前置 vs 后置递增:++aa++ 的签名区别

前置递增(++a)返回引用,后置(a++)返回旧值,靠一个无用的 int 参数区分:

Vec& operator++() { // 前置     ++x_; ++y_;     return *this; } Vec operator++(int) { // 后置:int 是占位符,不使用     Vec old = *this;     ++(*this); // 复用前置逻辑     return old; }

常见错误是把后置写成 Vec& operator++(int) —— 返回局部对象的引用,导致未定义行为;或者忘记参数 int,编译器会把它和前置重载冲突,报错 redefinition of 'operator++'

真正难处理的是当类管理动态内存时,后置递增的拷贝成本可能很高,这时候得权衡是否禁用后置版本(删掉它,或只提供前置),避免用户无意中写出低效代码。

text=ZqhQzanResources