C++标准硬性禁止重载5个运算符:.(成员访问)、::(作用域限定)、.*(成员指针访问)、?:(三目条件)、sizeof(大小计算),因它们是语言底层基石,重载会破坏语法解析、作用域机制、ABI兼容性、表达式结构及编译期语义。

哪些运算符在 C++ 中根本不能重载
直接说结论:C++ 标准硬性禁止重载 5 个运算符,写代码时只要出现 operator.、operator::、operator.*、operator?: 或 operator sizeof,编译器会立刻报错,没有商量余地。
为什么这 5 个运算符被锁死
它们不是“功能可以改”,而是语言底层机制的基石,改动会破坏整个解析逻辑:
-
.是访问对象成员的唯一入口,如果允许重载,obj.member就可能不指向真实内存布局,类对象模型就崩了 -
::控制作用域查找路径(比如std::vector),重载它会让命名空间和类的作用域语义彻底混乱 -
.*和->*(虽没列在禁令主表但同理)专用于成员指针解引用,属于 ABI 级别敏感操作 -
?:的三目结构(条件 ? 表达式1 : 表达式2)语法上无法拆成函数调用形式,编译器没法映射到任何operator?函数 -
sizeof在编译期求值,不产生运行时代码,而重载函数是运行时实体,二者根本不在一个维度
容易误判的“看似能重载”陷阱
有些运算符虽然能重载,但有强约束,常被当成“不能”——其实只是写法受限:
-
=、[]、()、->必须声明为类的 成员函数,不能写成全局operator= 和 <code>>>(流操作)必须是非成员函数,且通常得是 友元 才能访问私有成员;写成成员函数会导致cout 编译失败,因为左操作数 <code>cout不是你的类类型-
typeid虽然也在禁令列表里,但它本质是运算符+关键字组合,不是纯运算符,所以连提都不能提——不存在operator typeid这种东西
真正自由但必须守规矩的重载范围
其余所有常见运算符都可重载,但红线不能碰:
立即学习“C++免费学习笔记(深入)”;
- 不能改变优先级:
a + b * c永远是a + (b * c),哪怕你把operator+写得再慢,也不会变成(a + b) * c - 不能改变操作数个数:二元
+重载后仍是两个参数,operator+(a, b, c)直接非法 - 不能发明新符号:
operator**、operator@、operator~!全部拒收 - 语义要靠谱:把
operator+实现成内存拷贝或日志打印,编译能过,但协作时会被队友物理打断
最常被忽略的一点:重载函数签名是否匹配调用上下文,比能不能重载更重要。比如 5 + obj 要成功,operator+ 就不能是 MyClass::operator+ 成员函数——因为左操作数 5 是内置类型,没成员函数可调。这时候必须用非成员版本,否则就是编译错误,不是“不能重载”,而是“没写对位置”。


















