news 2026/6/3 1:23:03

【C++ 从基础到项目实战】C++(八):运算符重载——让你的类用起来像内置类型

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【C++ 从基础到项目实战】C++(八):运算符重载——让你的类用起来像内置类型

📌 阅读时长:25分钟 | 关键词:C++、运算符重载、operator、友元重载、<<重载、String类

引言

你有没有想过:为什么int可以a + bstring可以s1 + s2,而自己写的MyVector类只能用v.add(w)这种丑陋的语法?答案是运算符重载——它允许你为自定义类型定义+-<<等运算符的行为,让代码像操作内置类型一样自然。

一、运算符重载基础

1.1 概念与语法

运算符重载本质上就是给自定义类写一个特殊的函数,函数名是operator+ 运算符:

返回类型operator运算符(参数列表){// 实现逻辑}
classComplex{public:doublereal,imag;Complex(doubler=0,doublei=0):real(r),imag(i){}// 重载 + 运算符(成员函数)Complexoperator+(constComplex&other)const{returnComplex(real+other.real,imag+other.imag);}};intmain(){Complexc1(2,3),c2(4,5);Complex c3=c1+c2;// 等价于 c1.operator+(c2)// c3 = (6, 8i)}

1.2 可重载 vs 不可重载

可重载不可重载
+-*/%.成员访问
==!=<><=>=.*成员指针访问
=+=-=*=/=::作用域解析
++--(前后缀)sizeof
<<>>(流)?:三元条件
[]()(下标/函数调用)typeid
newdelete###预处理

1.3 两种重载方式

方式语法左操作数使用场景
成员函数Ret operatorX(Para)必须是本类对象单目运算符、赋值类
友元函数friend Ret operatorX(L,R)可以是其他类型双目运算符、流运算符
// 成员函数版本Complexoperator+(constComplex&other)const;// 等价于 c1.operator+(c2)// 友元函数版本friendComplexoperator+(constComplex&a,constComplex&b);// 等价于 operator+(c1, c2)

💡 流运算符<<>>必须用友元函数,因为左操作数是std::ostream而非本类。

二、各类运算符重载实例

2.1 算术运算符 (+, -, *, /)

classComplex{public:doublereal,imag;Complex(doubler=0,doublei=0):real(r),imag(i){}Complexoperator+(constComplex&o)const{returnComplex(real+o.real,imag+o.imag);}Complexoperator-(constComplex&o)const{returnComplex(real-o.real,imag-o.imag);}Complexoperator*(constComplex&o)const{returnComplex(real*o.real-imag*o.imag,real*o.imag+imag*o.real);}};

2.2 关系运算符 (==, !=, <, >)

classPoint{public:intx,y;Point(intx,inty):x(x),y(y){}booloperator==(constPoint&o)const{returnx==o.x&&y==o.y;}booloperator!=(constPoint&o)const{return!(*this==o);// 复用 ==}};

2.3 赋值运算符与复合赋值 (+=, -=)

classMyNumber{public:intvalue;MyNumber(intv):value(v){}MyNumber&operator=(constMyNumber&o){// 返回引用,支持链式赋值if(this!=&o)value=o.value;return*this;}MyNumber&operator+=(constMyNumber&o){value+=o.value;return*this;}};// a = b = c; // 链式赋值,依赖返回引用

2.4 自增自减 (++, --)

区分前缀和后缀的秘诀:后缀版本多一个不用的 int 参数

classCounter{public:intvalue;Counter&operator++(){// 前缀 ++++value;return*this;}Counteroperator++(int){// 后缀 ++ (int 是标记)Counter temp=*this;++value;returntemp;// 返回旧值}};Counter c{5};++c;// c.value = 6, 返回 c 自己c++;// c.value = 7, 返回 Counter(6)

2.5 流运算符 (<<, >>):必须用友元

classComplex{public:doublereal,imag;Complex(doubler=0,doublei=0):real(r),imag(i){}friendstd::ostream&operator<<(std::ostream&os,constComplex&c);friendstd::istream&operator>>(std::istream&is,Complex&c);};std::ostream&operator<<(std::ostream&os,constComplex&c){os<<c.real<<" + "<<c.imag<<"i";returnos;// 必须返回 os,支持链式调用}std::istream&operator>>(std::istream&is,Complex&c){is>>c.real>>c.imag;returnis;}// std::cout << c1 << " and " << c2 << std::endl; ✅ 链式

2.6 下标运算符 []

classIntArray{private:int*data;intsize;public:IntArray(ints):size(s),data(newint[s]){}int&operator[](intindex){// 返回引用,允许修改returndata[index];}constint&operator[](intindex)const{// const 版本,只读returndata[index];}~IntArray(){delete[]data;}};IntArrayarr(5);arr[2]=100;// 调用非 const 版本

2.7 函数调用运算符 () — 仿函数

classAdder{public:intoperator()(inta,intb)const{returna+b;}};Adder add;std::cout<<add(3,4)<<std::endl;// 7,像函数一样调用对象!

三、运算符重载最佳实践

原则说明
保持语义一致+不应该做减法
不要滥用只有提高可读性时才重载
算术运算返回新对象不返回引用(临时对象)
赋值运算返回引用return *this,支持链式
const 正确性不修改对象的函数加const
不可改变优先级重载不改变运算符优先级和结合性

四、std::string 类:运算符重载的教科书范本

std::string大量使用运算符重载,让字符串操作如内置类型般自然:

#include<string>std::string s1="Hello";std::string s2=" World";std::string s3=s1+s2;// + 重载:连接字符串s3+="!";// += 重载:追加if(s1==s2){}// == 重载:比较内容charc=s3[0];// [] 重载:下标访问std::cout<<s3;// << 重载:输出

常用 string 操作速查

方法功能示例
+/+=连接/追加s1 + s2
find(s)查找子串位置s.find("He")→ 0
substr(pos, n)截取子串s.substr(0, 3)→ “Hel”
replace(pos, n, s)替换s.replace(0,2,"Hi")
length()/size()长度s.length()
c_str()转 C 串s.c_str()const char *
at(i)安全下标访问(越界抛异常)s.at(100)

string vs C 风格字符串

std::stringchar[]/char *
内存管理自动手动
安全性不易溢出容易缓冲区溢出
操作便利丰富的成员函数<cstring>函数
推荐度⭐⭐⭐⭐⭐⭐⭐(仅在 C 接口需要)

小结

序号知识点一句话总结
1运算符重载operatorX特殊函数,让类支持运算符操作
2成员 vs 友元成员用于单目/赋值,友元用于双目/流运算符
3不可重载运算符..*::sizeoftypeid?:###
4流运算符必须用友元,返回ostream&支持链式
5前后缀 ++前缀无参,后缀有废弃 int 标记
6赋值 vs 算术赋值返回*this引用;算术返回新对象
7std::string运算符重载的典范,优先于 C 风格字符串

下一篇文章,我们将学习友元与设计模式初探——如何用friend打破封装边界,以及如何用 Singleton 模式用静态成员打造全局唯一实例。


本文是「C++ 从基础到项目实战」系列的第 8 篇。关注我,不错过后续更新。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/3 1:21:53

路由静态配置和动态配置

目录 1.需要用到的命令 2.路由静态配置 3.路由动态配置 1.需要用到的命令 1.进入特权模式命令 R2>enable R2#2.进入配置模式 R2#config t R2(config)#3.进入端口IP配置 R2(config)#int Gig0/0 R2(config-if)#4.配置端口IP地址 ip address 192.168.16.1 255.255.255.05.启…

作者头像 李华
网站建设 2026/6/3 1:21:24

记忆迁移规划技术:LLM驱动的机器人自适应控制

1. 记忆迁移规划技术概述记忆迁移规划&#xff08;Memory Transfer Planning&#xff0c;MTP&#xff09;是一项突破性的机器人控制技术&#xff0c;它巧妙地将大型语言模型&#xff08;LLM&#xff09;的代码生成能力与经验复用机制相结合。这项技术的核心创新在于建立了一个动…

作者头像 李华
网站建设 2026/6/3 1:15:38

私有化音视频系统/视频直播点播EasyDSS一体化音视频平台助力校园全场景数字化转型

教育信息化建设迈入纵深落地阶段&#xff0c;智慧校园建设核心目标是依托数字化手段打破地域与校区空间壁垒&#xff0c;打通优质师资、课程、校务管理资源流转链路。私有化音视频平台EasyDSS立足校园数据自主可控刚需&#xff0c;集成视频会议、实时直播、点播三大核心能力&am…

作者头像 李华