当前位置: 首页 > news >正文

C++类_运算符的重载

在 C++11 中,运算符重载允许你为自定义类型重新定义运算符的行为,使得自定义类型的对象能够像内置类型一样使用运算符。下面为你详细介绍 C++11 中运算符重载的相关内容,包含基本概念、语法、可重载的运算符、注意事项以及示例。

基本概念

运算符重载是一种特殊的函数,它使用运算符作为函数名。通过运算符重载,你可以让自定义类型的对象使用诸如 +-*/ 等运算符,以实现自定义的操作逻辑。

语法

运算符重载函数的定义语法如下:

返回类型 operator 运算符 (参数列表) {// 函数体
}

这里的 operator 是关键字,运算符 代表要重载的运算符,参数列表 则依据运算符的特性和需求来确定。

可重载的运算符

C++ 中大多数运算符都能被重载,但也有部分运算符不能重载,比如 ..*::?: 等。常见可重载的运算符如下,函数格式的声明参考附录。

  • 算术运算符+-*/%
  • 关系运算符==!=><>=<=
  • 逻辑运算符&&||!
  • 位运算符&|^~<<>>
  • 赋值运算符=+=-=*=/=%= 等
  • 自增自减运算符++--
  • 函数调用运算符()
  • 下标运算符[]

注意事项

  1. 不能改变运算符的优先级和结合性:运算符重载只是重新定义运算符的操作逻辑,不会改变其原有的优先级和结合性。
  2. 至少有一个操作数是自定义类型:运算符重载函数的参数中至少要有一个是自定义类型的对象,这样才能实现对自定义类型的操作。
  3. 避免过度重载:运算符重载应该遵循合理的语义,避免让代码变得难以理解。

示例

1. 重载 + 运算符
#include <iostream>class Complex {
private:double real;double imag;
public: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);}void display() const {std::cout << real << " + " << imag << "i" << std::endl;}
};int main() {Complex c1(1, 2);Complex c2(3, 4);Complex c3 = c1 + c2;c3.display();return 0;
}

在这个例子里,Complex 类代表复数,通过重载 + 运算符实现了两个复数的相加。

2. 重载 == 运算符
#include <iostream>class Point {
private:int x;int y;
public:Point(int a = 0, int b = 0) : x(a), y(b) {}// 重载 == 运算符bool operator==(const Point& other) const {return (x == other.x) && (y == other.y);}
};int main() {Point p1(1, 2);Point p2(1, 2);Point p3(3, 4);if (p1 == p2) {std::cout << "p1 and p2 are equal." << std::endl;}if (p1 != p3) {std::cout << "p1 and p3 are not equal." << std::endl;}return 0;
}

此示例中,Point 类代表二维平面上的点,通过重载 == 运算符来判断两个点是否相等。

3. 重载 ++ 运算符(前置和后置)
#include <iostream>class Counter {
private:int value;
public:Counter(int v = 0) : value(v) {}// 前置 ++ 运算符重载Counter& operator++() {++value;return *this;}// 后置 ++ 运算符重载Counter operator++(int) {Counter temp = *this;++(*this);return temp;}int getValue() const {return value;}
};int main() {Counter c(5);// 前置 ++Counter c1 = ++c;std::cout << "After pre-increment: " << c1.getValue() << std::endl;// 后置 ++Counter c2 = c++;std::cout << "After post-increment: " << c2.getValue() << std::endl;return 0;
}

在这个示例中,Counter 类代表计数器,分别重载了前置和后置 ++ 运算符。前置 ++ 返回引用,后置 ++ 通过一个 int 类型的占位参数来区分,返回临时对象。

附录

运算符分类运算符函数参数格式说明
算术运算符+成员函数:返回类型 operator+(const 类名& other) const;
非成员函数:返回类型 operator+(const 类名& lhs, const 类名& rhs);
实现加法操作,成员函数的 other 表示右操作数,非成员函数的 lhs 和 rhs 分别表示左操作数和右操作数。
-成员函数:返回类型 operator-(const 类名& other) const;
非成员函数:返回类型 operator-(const 类名& lhs, const 类名& rhs);
实现减法操作。
*成员函数:返回类型 operator*(const 类名& other) const;
非成员函数:返回类型 operator*(const 类名& lhs, const 类名& rhs);
实现乘法操作。
/成员函数:返回类型 operator/(const 类名& other) const;
非成员函数:返回类型 operator/(const 类名& lhs, const 类名& rhs);
实现除法操作。
%成员函数:返回类型 operator%(const 类名& other) const;
非成员函数:返回类型 operator%(const 类名& lhs, const 类名& rhs);
实现取模操作。
关系运算符==成员函数:bool operator==(const 类名& other) const;
非成员函数:bool operator==(const 类名& lhs, const 类名& rhs);
判断两个对象是否相等,返回 bool 类型。
!=成员函数:bool operator!=(const 类名& other) const;
非成员函数:bool operator!=(const 类名& lhs, const 类名& rhs);
判断两个对象是否不相等,返回 bool 类型。
>成员函数:bool operator>(const 类名& other) const;
非成员函数:bool operator>(const 类名& lhs, const 类名& rhs);
判断左操作数是否大于右操作数,返回 bool 类型。
<成员函数:bool operator<(const 类名& other) const;
非成员函数:bool operator<(const 类名& lhs, const 类名& rhs);
判断左操作数是否小于右操作数,返回 bool 类型。
>=成员函数:bool operator>=(const 类名& other) const;
非成员函数:bool operator>=(const 类名& lhs, const 类名& rhs);
判断左操作数是否大于等于右操作数,返回 bool 类型。
<=成员函数:bool operator<=(const 类名& other) const;
非成员函数:bool operator<=(const 类名& lhs, const 类名& rhs);
判断左操作数是否小于等于右操作数,返回 bool 类型。
逻辑运算符&&成员函数:bool operator&&(const 类名& other) const;
非成员函数:bool operator&&(const 类名& lhs, const 类名& rhs);
实现逻辑与操作,返回 bool 类型。但不建议重载逻辑与和逻辑或运算符,因为它们的短路特性可能会丢失。
`||成员函数:`bool operator||(const 类名 & other) const; 非成员函数:bool operator||(const 类名 & lhs, const 类名 & rhs);``实现逻辑或操作,返回 bool 类型。同样不建议重载,避免丢失短路特性。
!成员函数:bool operator!() const;
非成员函数:bool operator!(const 类名& obj);
实现逻辑非操作,返回 bool 类型。
位运算符&成员函数:返回类型 operator&(const 类名& other) const;
非成员函数:返回类型 operator&(const 类名& lhs, const 类名& rhs);
实现按位与操作。
`|`成员函数:` 返回类型 operator|(const 类名 & other) const; 非成员函数:返回类型 operator|(const 类名 & lhs, const 类名 & rhs);`实现按位或操作。
^成员函数:返回类型 operator^(const 类名& other) const;
非成员函数:返回类型 operator^(const 类名& lhs, const 类名& rhs);
实现按位异或操作。
~成员函数:返回类型 operator~() const;
非成员函数:返回类型 operator~(const 类名& obj);
实现按位取反操作。
<<成员函数:返回类型 operator<<(int shift) const;
非成员函数:返回类型 operator<<(const 类名& obj, int shift);
实现左移操作。
>>成员函数:返回类型 operator>>(int shift) const;
非成员函数:返回类型 operator>>(const 类名& obj, int shift);
实现右移操作。
赋值运算符=成员函数:类名& operator=(const 类名& other);实现赋值操作,通常返回自身的引用。
+=成员函数:类名& operator+=(const 类名& other);实现复合赋值加法操作,返回自身的引用。
-=成员函数:类名& operator-=(const 类名& other);实现复合赋值减法操作,返回自身的引用。
*=成员函数:类名& operator*=(const 类名& other);实现复合赋值乘法操作,返回自身的引用。
/=成员函数:类名& operator/=(const 类名& other);实现复合赋值除法操作,返回自身的引用。
%=成员函数:类名& operator%=(const 类名& other);实现复合赋值取模操作,返回自身的引用。
&=成员函数:类名& operator&=(const 类名& other);实现复合赋值按位与操作,返回自身的引用。
`|=`成员函数:` 类名 & operator|=(const 类名 & other);`实现复合赋值按位或操作,返回自身的引用。
^=成员函数:类名& operator^=(const 类名& other);实现复合赋值按位异或操作,返回自身的引用。
<<=成员函数:类名& operator<<=(int shift);实现复合赋值左移操作,返回自身的引用。
>>=成员函数:类名& operator>>=(int shift);实现复合赋值右移操作,返回自身的引用。
自增自减运算符++(前置)成员函数:类名& operator++();前置自增运算符,返回自身的引用。
++(后置)成员函数:类名 operator++(int);后置自增运算符,int 为占位参数,返回临时对象。
--(前置)成员函数:类名& operator--();前置自减运算符,返回自身的引用。
--(后置)成员函数:类名 operator--(int);后置自减运算符,int 为占位参数,返回临时对象。
函数调用运算符()成员函数:返回类型 operator()(参数列表);使对象可以像函数一样被调用。
下标运算符[]成员函数:返回类型& operator[](索引类型 index);
常成员函数:const 返回类型& operator[](索引类型 index) const;
实现对象的下标访问,返回引用以便可以进行读写操作。常成员函数用于 const 对象,返回 const 引用。
其他运算符->成员函数:返回类型 operator->();重载箭头运算符,通常用于智能指针类,返回一个指针或者一个重载了 -> 运算符的对象。
,成员函数:返回类型 operator,(const 类名& other);
非成员函数:返回类型 operator,(const 类名& lhs, const 类名& rhs);
重载逗号运算符,不建议轻易重载,因为逗号运算符的语义较为固定。
newdelete静态成员函数:void* operator new(size_t size);
静态成员函数:void operator delete(void* ptr);
静态成员函数:void* operator new[](size_t size);
静态成员函数:void operator delete[](void* ptr);
重载内存分配和释放运算符,new 用于分配内存,delete 用于释放内存。new[] 和 delete[] 用于数组的内存分配和释放。

相关文章:

  • 线性DP(动态规划)
  • flask 获取各种请求数据:GET form-data x-www-form-urlencoded JSON headers 上传文件
  • 物联网智能项目之——智能家居项目的实现!
  • 开源项目实战学习之YOLO11:ultralytics-cfg-models-rtdetr(十一)
  • 循环缓冲区
  • 实验-组合电路设计1-全加器和加法器(数字逻辑)
  • 大数据:驱动技术创新与产业转型的引擎
  • 节流 和 防抖的使用
  • 【C语言练习】018. 定义和初始化结构体
  • ai之paddleOCR 识别PDF python312和paddle版本冲突 GLIBCXX_3.4.30
  • 提升办公效率的PDF转图片实用工具
  • 学习黑客资产威胁分析贴
  • 《MATLAB实战训练营:从入门到工业级应用》趣味入门篇-用声音合成玩音乐:MATLAB电子琴制作(超级趣味实践版)
  • NocoDB:开源的 Airtable 替代方案
  • 二叉树最近公共祖先(后序遍历,回溯算法)
  • springboot war包tomcat中运行报错,启动过滤器异常,一个或多个筛选器启动失败。
  • 关于Python:7. Python数据库操作
  • 经典算法 求解硬币组成问题
  • 基于大模型的肾结石诊疗全流程风险预测与方案制定研究报告
  • 软件测评如何保障质量与提升体验?从五方面详细说说
  • 央视315晚会曝光“保水虾仁”后,湛江4家涉事企业被罚超800万元
  • 央行、证监会:科技创新债券含公司债券、企业债券、非金融企业债务融资工具等
  • 短剧剧组在贵州拍戏突遇极端天气,演员背部、手臂被冰雹砸伤
  • 国际上首次,地月空间卫星激光测距试验在白天成功实施
  • 美权威人士批“特朗普对进口电影征关税”:将杀死美电影产业
  • 体坛联播|拜仁提前2轮德甲夺冠,赵心童11比6暂时领先