news 2026/5/7 9:43:03

c++面向对象——运算符重载

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
c++面向对象——运算符重载

运算符重载

c++运算符

c++中的运算符:可以分为单目、二目、三目运算符。单目运算符只有一个操作数,二目运算符有两个操作数,三目运算符有三个操作数。也可叫做一元、二元、三元运算符。

单目运算符:

a++ ++a a-- --a !a ~a +a -a &a *a static_cast<T>(a)

new a delete a delete[] asizeof a

二目运算符:

o->a o(a) o[a] a * b a / b a + b a - b a % b a << b a >> b

a < b a <= b a > b a >= b a == b a != b a & b a | b a ^ b

a && b a || b a = b a += b a -= b a *= b a /= b a %= b a <<= b

a >>= b a &= b a |= b a ^= b new T[a]a, bn::ao.a

三目运算符:

a ? b : c

对于内建类型,运算符是在c++语言中定义好的。自定义类型想要使用运算符往往需要进行运算符重载。

其中背景灰色的运算符例子是无法重载的。

自定义类型运算符重载

对于c++内建类型int,可以直接使用运算符:

int a = 5; int b = a + 4;

自定义类型如果想要使用运算符往往需要进行运算符重载:

//复数类型 Complex c1 (5, 6); Complex c2 = c1 + 4; ↓ Complex::operator +(int) //√ int::operator +(int) ? //×

对于自定义类型使用运算符,本质是调用自定义类型的一个函数。函数名是以 "operator 运算符" 表示的。自定义类型的运算符重载本质是函数重载。使用运算符时,本质是使用对应运算符函数的语法糖。对于自定义类型,这种函数是为了使其支持运算符重载,而内建类型并不存在这种函数。

二元运算符例

自定义一个类表示虚数,在类中使用 operator + 重载+运算符。

class Complex { public: Complex(int real, int image); Complex operator +(const Complex& c) const; Complex operator +(int r) const; void ShowComplex() const; private: int r_, i_; }; Complex::Complex(int real, int image) :r_(real), i_(image) {}; Complex Complex::operator +(const Complex& c) const { return Complex(r_ + c.r_, i_ + c.i_); }; Complex Complex::operator +(int r) const { return Complex(r_ + r, i_); } void Complex::ShowComplex() const{ std::cout << r_ << "_" << i_ << std::endl; } int main() { Complex complex1(5, 6); Complex complex2 = complex1 + 4; Complex complex3 = complex2 + complex1; Complex complex4 = complex1.operator+(complex2); complex1.ShowComplex(); complex2.ShowComplex(); complex3.ShowComplex(); complex4.ShowComplex(); }

使用operator +定义一个虚数 + 虚数的函数。返回值为 Complex类型,参数代表+号右边的操作数,而+号左边的操作数默认为operator +所在的自定义类型。由于 +运算 不改变所使用的两个操作数,用const修饰表示只读。括号内的const修饰括号中的参数;而后面的const修饰函数本身,表示operator所在的自定义类型只读,可以理解为this是只读的。

函数中直接在return时使用构造函数返回一个 Complex类型。

Complex Complex::operator +(const Complex& c) const { return Complex(r_ + c.r_, i_ + c.i_); };

同样也可以将参数定义为 int类型 重载运算符,这样可以在 +号 右边直接加上 int类型 的数据。

Complex Complex::operator +(int r) const { return Complex(r_ + r, i_); }

运算符重载本质是函数重载,使用 + 运算符等价于直接使用函数。

Complex complex4 = complex1.operator+(complex2);

上面的代码运行结果为:

5_6 9_6 14_12 14_12

如果自定义类型是已经封装好的,或者左操作数不是自定义类型,也可以在自定义类型外声明运算符重载。不过这样的外部函数无法调用类中被声明为private的私有属性,可以将外部函数声明为友元来解决。

class Complex { public: Complex(int real, int image); friend Complex operator +(const Complex& c1, const Complex& c2); friend Complex operator +(int r, const Complex& c); void ShowComplex(); private: int r_, i_; }; Complex operator +(const Complex& c1, const Complex& c2) { return Complex(c1.r_ + c2.r_, c1.i_ + c2.i_); } Complex operator +(int r, const Complex& c) { return Complex(r + c.r_, c.i_); }

一元运算符例

//一元运算符重载 class Complex { public: Complex(int real, int image); //取负数运算符重载 Complex operator-() const; //自增运算符重载 Complex& operator++(); //后置自增运算符重载 Complex operator++(int); void ShowComplex() const; private: int r_, i_; }; Complex::Complex(int real = 0, int image = 0) :r_(real), i_(image) { }; Complex Complex::operator-() const { return Complex(-r_, -i_); }; //全局运算符重载 //Complex operator-(const Complex& c) { // return Complex(-c.r_, -c.i_); //} Complex& Complex::operator++() { ++r_; ++i_; return *this; } Complex Complex::operator++(int) { Complex temp(*this); //保存自增前的值 ++r_; ++i_; return temp; } void Complex::ShowComplex() const { std::cout << r_ << "_" << i_ << std::endl; } int main() { Complex complex1(5, 6); Complex complex2 = -complex1; //Complex complex2 = operator-(complex1); complex1.ShowComplex(); complex2.ShowComplex(); std::cout << "自增运算符重载:" << std::endl; ++complex1; complex1.ShowComplex(); Complex complex3 = ++complex1; complex3.ShowComplex(); complex1.ShowComplex(); std::cout << "后置自增运算符重载:" << std::endl; Complex complex4 = complex1++; complex4.ShowComplex(); complex1.ShowComplex(); }

在一元运算符中,可以定义比如取负数的运算符。

需要注意自增和后置自增在使用时返回值有所不同。使用 operator++() 表示自增,operator++(int) 表示后置自增,看起来像是二目运算符重载,不过int可以认为无意义,只是为了区分前置后置自增。

在前置自增中,返回的值经过了自增操作;在后置自增中,返回值发送后再进行自增,可以使用一个寄存变量保存自增前的值,最后返回这个寄存变量的值。

Complex& Complex::operator++() { ++r_; ++i_; return *this; } Complex Complex::operator++(int) { Complex temp(*this); //保存自增前的值 ++r_; ++i_; return temp; }

如果要用函数表示后置自增,可以这样表示。其中0对应的是参数中的int,没有实际意义。

Complex complex5 = complex1.operator++(0);

重载括号运算符

//重载()运算符 //函数对象(Functor)是一个重载了operator()运算符的类的对象。它可以像函数一样被调用,并且可以携带状态。 struct Invoker { int arg_; int (*func)(int, int); int operator() (int a) { return func(arg_, a); } }; int f(int a, int b) { return a + b; } int main() { Invoker invoker{ 10, f }; int result = invoker(5); // 调用operator(),相当于f(10, 5) std::cout << "Result: " << result << std::endl; // 输出结果 return 0; }

'()' 也可以在类或结构体中被重载。重载了 '()' 的对象称作函数对象,因为在对象后加 '()' 可以直接使用重载的 '()运算符',这使得对象可以像函数一样被调用,所以叫做函数对象。函数对象的一个好处是可以携带状态。

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

Flask异步时代的降临:掌握 Flask 2.0+ 的 `async def` 视图与协程编写

更多内容请见: 《Python Web项目集锦》 - 专栏介绍和目录 文章目录 前言:历史的分水岭 第一章:认知升级——从 WSGI 到 ASGI 的底层跃迁 1.1 WSGI 的“同步枷锁” 1.2 ASGI 的“异步解放” 第二章:基础设施换血——告别 Werkzeug,拥抱 ASGI 服务器 2.1 为什么异步视图不能…

作者头像 李华
网站建设 2026/5/7 9:39:58

browser-use 的工作原理

browser-use 并不完全依赖 LLM 的视觉能力&#xff0c;它采用了混合策略&#xff1a; # browser-use 内部工作流程&#xff1a; 1. Playwright 获取页面 DOM 结构&#xff08;HTML/CSS/JavaScript&#xff09; 2. 将 DOM 转换为结构化文本描述 3. 发送给 LLM 进行分析和决策 4.…

作者头像 李华
网站建设 2026/5/7 9:34:35

百度网盘秒传链接提取脚本:5分钟掌握永久分享文件的终极指南

百度网盘秒传链接提取脚本&#xff1a;5分钟掌握永久分享文件的终极指南 【免费下载链接】rapid-upload-userscript-doc 秒传链接提取脚本 - 文档&教程 项目地址: https://gitcode.com/gh_mirrors/ra/rapid-upload-userscript-doc 你是否经常遇到百度网盘分享链接失…

作者头像 李华