【C++】操作符重载

article/2025/11/11 15:41:43

注意:操作符重载可以当做==“自定义类的运算”==

1 为什么需要操作符重载?
对于基础的变量,int等,不需要重载就知道如何做,但是对于自定义类,就无法进行运算,比如复数类。

2 操作符重载总结
1)操作符重载本质上是一个函数,可以采用 友元函数或者成员函数实现。但是采用这两种函数传递参数、实现代码、应用场合均不同。

全局函数与成员函数的比较:
传递参数:全局函数中不传递this指针,成员函数默认传递this指针,因此成员函数可以少一个参数;
属性访问:成员函数可以访问私有变量,全局函数需要转化为友元函数才可以。
应用场合:正常写法采用成员函数。必须采用全局函数重载的运算符有<<和>>,必须采用成员函数重载的运算符有=、()、[ ]、->四个。

2)操作符重载的格式:

#全局函数
int operator+(const A& a1, const A& a2)
#成员函数
int operator+(const A& obj)

函数名为operator与运算符的组合(可变);
输入为对象(可变,友元函数或成员函数实现);
返回值可以为元素、对象或者引用(可变)。

3)可以重载的运算符
在这里插入图片描述

3 实例:实现complex类的±运算符重载

注意:
1)使用友元函数重载需要注意的是,二元运算则传递两个参数,同时添加friend关键字,使用成员函数只需要一个参数。

#include <iostream>
using namespace std;class Complex
{
public:Complex(int a, int b){this->a = a;this->b = b;}friend Complex operator+(const Complex& x1, const Complex& x2);void printC(){cout << "a: " << this->a << "b:" << this->b << endl;}Complex operator-(const Complex& obj){Complex tmp(this->a - obj.a, this->b - obj.b);return tmp;}
private:int a;int b;
};//友元函数重载
Complex operator+(const Complex& x1, const Complex& x2)
{Complex tmp(x1.a + x2.a, x1.b + x2.b);return tmp;
}
void main()
{Complex x1(1, 2);Complex x2(3, 4);Complex x3 = x1 + x2;x3.printC();Complex x4 = x2 - x1;x4.printC();cout << "hello,world..." << endl;system("pause");
}

4 实例:基于3实现Complex类的前置–以及后置++

注意:
1)后置++需要在参数列表中增加占位符int,Complex operator++(Complex& obj, int)。
2)后置++先使用后++,如a++,在具体实现时就要先使用临时变量tmp暂存输入,而后++,最后返回临时变量。
3)使用成员函数实现比友元函数实现少一个参数,这个参数通过this指针传递。
4)传递的变量最好在引用&前使用const,保持变量的内存空间不能改变。

#include <iostream>
using namespace std;class Complex
{
public:friend Complex operator+(const Complex& x1, const Complex& x2);friend Complex operator++(Complex& obj, int);Complex(int a, int b){this->a = a;this->b = b;}void printC(){cout << "a: " << this->a << "b:" << this->b << endl;}Complex operator-(const Complex& obj)//-{Complex tmp(this->a - obj.a, this->b - obj.b);return tmp;}//成员函数实现前置--Complex& operator--(){this->a++;this->b++;return *this;}
private:int a;int b;
};Complex operator+(const Complex& x1, const Complex& x2)
{Complex tmp(x1.a + x2.a, x1.b + x2.b);return tmp;
}//友元函数实现后置++,后置需要增加占位符
Complex operator++(Complex& obj, int)
{Complex tmp = obj;//其中如果有指针,那么需要注意浅拷贝obj.a++;obj.b++;return tmp;
}
void main()
{Complex x1(1, 2);Complex x2(3, 4);Complex x3 = x1 + x2;x3.printC(); //4,6--x3;Complex x4 = x2 - x1;x4.printC();//2,2Complex x5 = x4++;x4.printC();//3,3x5.printC();//2,2cout << "hello,world..." << endl;system("pause");
}

5 实例:实现Complex左移<<和>>右移操作符重载 (二元运算符两个参数不同的情况)

注意:
1)类似<<操作符重载,其为二元运算符,两个操作数类型不同,分别为ostream和Complex(比如)。
2)实现两个操作数类型不同的运算符重载要使用友元函数。

  • 原因是,成员函数重载operator+,调用a+1时相当于调用的a.operator(1),只能保证一种参数顺序的运算,两个参数更换位置就失败,如a+1,(a为Complex),1+a就会报没有对应的运算符重载。
  • 友元函数可以通过重载友元函数来实现,只调换换参数位置即可实现。

3)要实现链式编程,返回引用。cout<<a<<endl。

#include <iostream>
using namespace std;class Complex
{
public:friend ostream& operator<<(ostream& out, const Complex& obj);friend Complex operator+(const Complex& x1, int i);friend Complex operator+(int i, const Complex& x1);friend istream& operator>>(istream& in, Complex& obj);Complex(int a, int b){this->a = a;this->b = b;}void printC(){cout << "a: " << this->a << "b:" << this->b << endl;}Complex operator-(int i) //成员函数重载-{Complex tmp(this->a - i, this->b - i);return tmp;}private:int a;int b;
};Complex operator+(const Complex& x1, int i) //友元函数重载+1{Complex tmp(x1.a + i, x1.b + i);return tmp;
}
Complex operator+(int i, const Complex& x1)//友元函数重载+2{Complex tmp(x1.a + i, x1.b + i);return tmp;
}//友元函数实现重载<<左移操作符,输出,且只能采用友元函数
ostream& operator<<(ostream& out, const Complex& obj)//此处将ostream类型的out变量本身返回,以便后续的连续操作
{cout << obj.a << " + " << obj.b << "i" << endl;return out;
}#原来自己是这么实现的,但是不支持cin>>x1>>x2的链式编程的情况
// void operator>>(istream& in, Complex& obj)
// {
// 	in >> obj.a;
// 	in >> obj.b;
// }
istream& operator>>(istream& in, Complex& obj)
{in >> obj.a;in >> obj.b;return in;
}
void main()
{Complex x1(1, 2);Complex x2(2, 3);cout << x1 + 1 << endl;cout << 1 + x1 << endl;cout << x1 - 2 << endl;cin >> x1 >> x2;cout << x1 << endl;cout << "hello,world..." << endl;system("pause");
}

在这里插入图片描述

6 重载=等号操作符
有指针的类定义的对象,在等号=赋值时,采用C++的赋值,进行的是浅拷贝,导致两个对象的指针指向同一个内存空间,释放的时候出现问题。
在这里插入图片描述

#include <iostream>
using namespace std;class Name
{
public:Name(const char* p)//“asdb”{if (p == NULL){this->m_len = 0;this->m_p = new char[this->m_len + 1];strcpy(this->m_p, "");}else{this->m_len = strlen(p);this->m_p = new char[this->m_len + 1];strcpy(this->m_p, p);}}Name(const Name& obj){this->m_len = obj.m_len;this->m_p = new char[this->m_len + 1];strcpy(this->m_p, obj.m_p);}~Name(){if (this->m_len != NULL){delete[] this->m_p;this->m_p = NULL;this->m_len = 0;}}Name& operator=(const Name& obj)//重载等号操作符,实现连等,返回一个引用{if (this->m_p!=NULL) //先释放旧的指针{delete[] this->m_p;this->m_p = NULL;this->m_len = 0;}this->m_len = obj.m_len;this->m_p = new char[this->m_len + 1];strcpy(this->m_p, obj.m_p);return *this; }
protected:
private:char* m_p;int m_len;
};void main()
{Name obj("asdf");//双引号代表字符串,单引号代表字符,并且其可转化为int的ASCII码Name obj2("sdgf");Name obj3 = obj2;obj2 = obj;cout << "hello,world..." << endl;system("pause");
}

注意:
字符串传递使用双引号;
定义字符串变量或者形参,都要使用const关键字修饰;
在进行赋值时,要先释放旧的指针指向的空间,再赋值。

7 数组类案例

链接:数组类

8 字符串类案例

链接:字符串类

9 重载()操作符

重载()操作符,在定义对象后,可以使用f(),类似于f.operator()操作。这种重载和python中的__call_ _()函数很像,可以给对象传参数,输出结果。

#include <iostream>
using namespace std;
class F
{
public:int operator()(int a, int b){return a + b;}
};
void main()
{F f;f(2, 4);cout << "hello,world..." << endl;system("pause");
}

10 不要重载&&以及||

作用于基础类型的&&和||有短路规则,但是经过重载后,就没有短路规则了,原因是重载是一种函数。

class Test
{
public:Test(int i = 0){this->i = i;}Test&  operator+(const Test& obj){this->i = this->i + obj.i;return *this;}bool operator&&(const Test& obj){return this->i && obj.i;}int getData(){return this->i;}
private:int i;
};
void main()
{Test t1(1);Test t2(2);t1 && (t1 + t2);//重载&&cout << "hello,world..." << endl;system("pause");
}

此处重载&&,但是仍然先计算+加号重载的操作符,后计算&&重载,而不是先判断t1。


http://chatgpt.dhexx.cn/article/g5R3qM5D.shtml

相关文章

C++ 操作符重载

输出操作符"<<" 和输入操作运算符">>" 操作符重载&#xff0c;也叫运算符重载&#xff0c;是C的重要组成部分&#xff0c;它可以让程序更加的简单易懂&#xff0c;简单的运算符使用可以使复杂函数的理解更直观。 操作符重载可对 已有的运算…

C++-操作符重载

定义&#xff1a; Salesitem.h /* * This file contains code from "C Primer, Fifth Edition", by Stanley B. * Lippman, Josee Lajoie, and Barbara E. Moo, and is covered under the * copyright and warranty notices given in that book: * * "Copyrig…

c++操作符重载

转自https://www.cnblogs.com/xudong-bupt/p/3557525.html 1.什么是操作符重载 可以使用分词将操作符重载理解为&#xff1a;操作符重载。 C中的操作符很多&#xff0c;如&#xff0c;-&#xff0c;*&#xff0c;\等等。 C中的重载也是C中面向对象多态的体现。 简单说操作符重…

操作符重载——C/C++学习笔记

此篇文章来自于网上&#xff0c;作为自己学习中的笔记&#xff0c;若有侵权行为&#xff0c;请告之&#xff0c;24小时之内必删除&#xff01;下面就转入正题吧&#xff01; 一、什么是操作符重载&#xff1f; 一看到重载&#xff0c;很容易就让人联想到成员函数重载&#xff0…

什么是操作符重载

一、什么是操作符重载 操作符重载可以分为两部分&#xff1a;“操作符”和“重载”。说到重载想必都不陌生了吧&#xff0c;这是一种编译时多态&#xff0c;重载实际上可以分为函数重载和操作符重载。运算符重载和函数重载的不同之处在于操作符重载重载的一定是操作符。我们不妨…

前端知识点总结 Vue JS CSS

前端知识点 MVVM和MVC的区别什么是Vue生命周期钩子函数触发顺序 VueVue优点父子通信&#xff0c;兄弟通信指令V-if和V-show区别 Vue-loaderVue-key的作用v-modalVue data必须是函数的问题Vue slot Vue-router多个router-viewroute与router的区别导航守卫懒加载 ES6JavaScript同…

JavaScript进阶之手写Promise

前言 Promise异步编程的一种解决方案&#xff0c;比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现&#xff0c;ES6 将其写进了语言标准&#xff0c;统一了用法&#xff0c;原生提供了Promise对象。这里手写一次&#xff0c;希望能和大家一起彻底…

【数据库】MongoDB数据库详解

目录 一&#xff0c;数据库管理系统 1&#xff0c; 什么是数据库 2&#xff0c;什么是数据库管理系统 二&#xff0c; NoSQL 是什么 1&#xff0c;NoSQL 简介 2&#xff0c;NoSQL数据库 3&#xff0c;NoSQL 与 RDBMS 对比 三&#xff0c;MongoDB简介 1&#xff0c; MongoDB 是什…

面试06,[长亮科技]()(offer)、[荔枝]()FM(在确定部门和薪资)、[涂鸦智能]()(第一轮电话面半小时,待后续)、华资软件(HR面)、[广州速游]()(已挂)。至于公司怎么样不加以言论。

作者&#xff1a;Carson-Zhao 链接&#xff1a;https://ac.nowcoder.com/discuss/522002?type2&order0&pos16&page1&ncTraceId&channel-1&source_iddiscuss_tag_nctrack 来源&#xff1a;牛客网 总结一下这几天的面试吧&#xff01;从19号到现在23号…

SQL Foundation(1--13)

1&#xff1a;关系数据库的由来&#xff1a; IBM的工程师Dr E F codd 的关系型数据库模型发表于1970 论文名称&#xff1a; A relational Model of data for Large Shared Data Bank (这个在wiki 和google上可以搜到) SQL: Structured query language&#xff1a; oracle官方…

一、快速入门 MongoDB 数据库

文章目录 一、NoSQL 是什么1.1 NoSQL 简史1.2 NoSQL 的种类及其特性1.3 NoSQL 特点1.4 NoSQL 的优缺点1.5 NoSQL 与 SQL 数据库的比较 二、MongoDB 基础知识2.1 MongoDB 是什么2.2 MongoDB 的体系结构2.3 MongoDB 的特点2.4 MongoDB 键特性2.5 MongoDB 的核心服务和工具2.6 Mon…

数据库总结(考研复试和期末复习皆可用)

数据库总结 点击下载该文档 密码&#xff1a;cqoq 本人自制了简答题的速记卡片 地址&#xff0c;大家可以参考使用。[下载Markji App 使用] 第一章 绪论 1.1 数据库系统概述 数据库管理系统(DBMS)的功能: 数据定义功能数据组织、存储和管理数据库操纵功能数据库的事务和运行…

一步步教你轻松学KNN模型算法

一步步教你轻松学KNN模型算法 ( 白宁超 2018年7月24日08:52:16 ) 导读&#xff1a;机器学习算法中KNN属于比较简单的典型算法&#xff0c;既可以做聚类又可以做分类使用。本文通过一个模拟的实际案例进行讲解。整个流程包括&#xff1a;采集数据、数据格式化处理、数据分析、数…

Oracle实战详解

Oracle实战详解 1.oracle介绍 ORACLE数据库系统是美国ORACLE公司&#xff08;甲骨文&#xff09;提供的以分布式数据库为核心的一组软件产品&#xff0c;是目前最流行的客户/服务器(CLIENT/SERVER)或B/S体系结构的数据库之一。比如SilverStream就是基于数据库的一种中间件。ORA…

数据库|SQL / MySQL的基本理论用法

本文从数据库MySQL的数据类型、关系模型、增删改查语句、管理MySQL、实用SQL语句、事务等方面进行介绍。 数据类型 对于一个关系表&#xff0c;除了定义每一列的名称外&#xff0c;还需要定义每一列的数据类型。关系数据库支持的标准数据类型包括数值、字符串、时间等&#xf…

KNN模型算法研究与案例分析

KNN模型算法研究与案例分析( 白宁超 2018年8月29日15:39:13 ) 导读&#xff1a;机器学习算法中KNN属于比较简单的典型算法&#xff0c;既可以做聚类又可以做分类使用。本文通过一个模拟的实际案例进行讲解。整个流程包括&#xff1a;采集数据、数据格式化处理、数据分析、数据归…

SQL总结

目录 简介 在Android中存储数据有时会用到数据库&#xff0c;Android给我们提供了 一系列的API来操作数据库&#xff0c;非常简单&#xff0c;我们只需要输入对应的SQL语句&#xff0c;甚至不懂SQL语句&#xff0c;只传入对应的参数即可使用。还有一些第三方库&#xff0c;如G…

Windows开机启动项设置详解

一、开机启动原理 Windows系统都有一个“启动”文件夹&#xff0c;把需要打开的程序的快捷方式或脚本放到“启动”文件夹里&#xff0c;就可以实现开机自启动。 启动”文件夹分为两种&#xff1a;“系统启动文件夹”和“用户启动文件夹”。 系统启动文件夹 Win10系统“启动”…

「C#」设置开机启动

自己写了个监控键盘按键的小程序。 在界面上实时显示按下的键&#xff0c;但是想实现程序的开机自启如何实现呢。 开机自启动一种是在windows的“C:\Users\用户名\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup”家快捷方式。但是这种方法自测有时候不成功。…

centos7 设置开机启动项

高端的废话就是没有引言这种废话。 1.这里我已我的centos7为例输入&#xff1a; systemctl list-unit-files #查看开机启动表如图下&#xff1a; 最左边就是服务 &#xff0c;最右边就是状态 。如当你想要服务器开机启动firewalld&#xff08;防火墙&#xff09;输入 system…