C++ :运算符重载
运算符重载:
运算符的重载实际是一种特殊的函数重载,必须定义一个函数,并告诉C++编译器,当遇到该重载的运算符时调用此函数。这个函数叫做运算符重载函数,通常为类的成员函数
定义运算符重载函数的一般格式
返回值类型 类名::operator重载的运算符(参数表) {.......}
operator是关键字,它与重载的运算符一起构成函数名。因函数名的特殊性,C++编译器可以将这类函数识别出来。
加号运算符重载:
作用:实现两个自定义数据类型相加的运算
1.成员函数实现 + 号运算符重载
#include <iostream>
using namespace std;//加号运算符重载class Person
{
public://1 成员函数实现 + 号运算符重载Person operator+(Person& p){Person temp;temp.m_A = this->m_A + p.m_A;temp.m_B = this->m_B + p.m_B;return temp;}int m_A;int m_B;
};void test01() {Person p1;p1.m_A = 10;p1.m_B = 10;Person p2;p2.m_A = 10;p2.m_B = 10;Person p3 = p1 + p2;cout << "p3.m_A = " << p3.m_A<< endl;cout << "p3.m_B = " << p3.m_B<< endl;
}int main() {test01();system("pause");return 0;
}
(2).全局函数重载:
class Person
{
public://1 成员函数实现 + 号运算符重载/*Person operator+(Person& p){Person temp;temp.m_A = this->m_A + p.m_A;temp.m_B = this->m_B + p.m_B;return temp;}*/int m_A;int m_B;
};//2.全局函数重载+号
Person operator+(Person& p1, const Person& p2)
{Person temp;temp.m_A = p1.m_A + p2.m_A;temp.m_B = p1.m_B + p2.m_B;return temp;
}//3 运算符重载 可以发生函数重载
Person operator+(Person& p1, int num)
{Person temp;temp.m_A = p1.m_A + num;temp.m_B = p1.m_B + num;return temp;
}void test01() {Person p1;p1.m_A = 10;p1.m_B = 10;Person p2;p2.m_A = 10;p2.m_B = 10;//成员函数方式Person p3 = p2 + p1; //相当于 p2.operaor+(p1)Person p3 = p1 + p2;//全局函数重载本质调用:Person p3 = operator+(p1, p2);Person p3 = p1 + p2;//cout << "p3.m_A = " << p3.m_A<< endl;cout << "p3.m_B = " << p3.m_B<< endl;
}int main()
{test01();system("pause");return 0;
}
2.左移运算符重载
#include <iostream>
using namespace std;//左移运算符重载class Person
{friend ostream& operator<<(ostream& cout, Person& p);public:Person(int a, int b){this->m_A = a;this->m_B = b;}
private:
//成员函数 实现不了 p << cout 不是我们想要的效果//void operator<<(Person& p){//}int m_A;int m_B;
};//全局函数实现左移重载
ostream& operator<<(ostream& cout, Person &p) //本质 operator<<(cout,p) 简化cout<<p
{cout << "m_A = " << p.m_A << " m_B = " << p.m_B;return cout;
}void test01()
{Person p(10,10);//p.m_A = 10;//p.m_B = 10;cout << p<<"hello world"<<endl; //链式编程 输出一个对象就能打印他的属性
} int main()
{test01();system("pause");return 0;
}
总结:重载左移运算符配合友元可以实现输出自定义数据类型
3.递增运算符重载
class MyInteger
{friend ostream& operator<<(ostream& cout, MyInteger myint);
public:MyInteger() {m_Num = 0;}private:int m_Num;
};//重载左移运算符
ostream& operator<<(ostream& cout, MyInteger myint)
{cout << myint.m_Num << endl; //全局函数想要访问私有属性return cout;
}
void test01()
{MyInteger myint;cout << myint << endl;}int main()
{test01();system("pause");return 0;
}
输出结果: 0
class MyInteger
{friend ostream& operator<<(ostream& cout, MyInteger myint);
public:MyInteger() {m_Num = 0;}//重载前置++运算符 返回引用为了一直对一个数据进行递增操作MyInteger& operator++(){//先++m_Num++;//再返回return *this;}//重载后置++运算符 //int代表占位参数,可以用于区分前置和后置递增MyInteger operator++(int){//先记录当时结果MyInteger temp = *this;//后递增m_Num++;//最后将记录结果做返回return temp;}private:int m_Num;
};//重载左移运算符
ostream& operator<<(ostream& cout, MyInteger myint)
{cout << myint.m_Num << endl; //全局函数想要访问私有属性return cout;
}
void test01()
{MyInteger myint;cout << ++myint << endl;}void test02()
{MyInteger myint;cout << myint++ << endl;cout << myint << endl;
}int main()
{// test01();test02();system("pause");return 0;
}
4.赋值运算符重载:
class Person
{
public:Person(int age){m_Age = new int(age); //把数据创建在堆区 }~Person(){if (m_Age != NULL){delete m_Age;m_Age = NULL;}} //释放堆区内存 int* m_Age;};void test01()
{Person p1(18);Person p2(20);p2 = p1; //赋值操作cout << "p1的年龄为:" << *p1.m_Age << endl;cout << "p2的年龄为:" << *p2.m_Age << endl;
}int main()
{test01();system("pause");return 0;
}
上示代码会崩;
崩溃原因:堆区内存重复释放
解决方法:
示例如下:
class Person
{
public:Person(int age){m_Age = new int(age); //把数据创建在堆区 }~Person(){if (m_Age != NULL){delete m_Age;m_Age = NULL;}} //释放堆区内存 //重载 赋值运算符 (编译器默认提供) 是一个浅拷贝的操作,创建在堆区d的属性,就会出现堆区内存重复释放Person& operator=(Person &p) //返回引用{//编译器提供的代码是浅拷贝//m_Age = p.m_Age;//应该先判断是否有属性在堆区,如果有先释放干净,然后再深拷贝if (m_Age != NULL){delete m_Age;m_Age = NULL;}//提供深拷贝 解决浅拷贝的问题m_Age = new int(*p.m_Age);//返回自身 为了实现连等return *this;}int* m_Age; //创建在堆区};void test01()
{Person p1(18);Person p2(20);Person p3(30);p3 = p2 = p1; //赋值操作cout << "p1的年龄为:" << *p1.m_Age << endl;cout << "p2的年龄为:" << *p2.m_Age << endl;cout << "p3的年龄为:" << *p3.m_Age << endl;}int main()
{test01();system("pause");return 0;
}
拷贝构造函数 与赋值重载函数的区别。
总结: 浅赋值与深复制。
什么时候使用深拷贝和深赋值。
在类型设计中,使用动态内存或使用内核对象时,必须重新实现拷贝构造函数和赋值重载
5.关系运算符重载:
class Person
{
public:Person(string name, int age) //用构造函数进行赋初值{m_Name = name;m_Age = age;}string m_Name;int m_Age;};void test01()
{Person p1("Tom", 18);Person p2("Tom", 18);if (p1 == p2) 、//err{cout << "a和b相等" << endl;}else{cout << "a和b不相等" << endl;}
}int main()
{test01();system("pause");return 0;
}
对于==
重载关系运算符,可以让两个自定义类型对象进行对比操作
class Person
{
public:Person(string name, int age) //用构造函数进行赋初值{m_Name = name;m_Age = age;}//重载 == 号bool operator==(Person& p){if (this->m_Name == p.m_Name && this->m_Age == p.m_Age){return true;}else{return false;}}string m_Name;int m_Age;};void test01()
{Person p1("Tom", 18);Person p2("Tom", 18);if (p1 == p2) //err 需要重载=={cout << "p1和p2相等" << endl;}else{cout << "p1和p2不相等" << endl;}
}int main()
{test01();system("pause");return 0;
}
对于!=
class Person
{
public:Person(string name, int age) //用构造函数进行赋初值{m_Name = name;m_Age = age;}//重载 == 号bool operator==(Person& p){if (this->m_Name == p.m_Name && this->m_Age == p.m_Age){return true;}else{return false;}}bool operator!=(Person& p){if (this->m_Name == p.m_Name && this->m_Age == p.m_Age){return false;}else{return true;}}string m_Name;int m_Age;};void test01()
{Person p1("Tom", 18);Person p2("Jerry", 18);if (p1 == p2) //err 需要重载=={cout << "p1和p2相等" << endl;}else{cout << "p1和p2不相等" << endl;}if (p1 != p2) //err 需要重载=={cout << "p1和p2是不相等" << endl;}else{cout << "p1和p2相等" << endl;}
}int main()
{test01();system("pause");return 0;
}
运行结果:
6.函数调用运算符重载
//打印输出类
class MyPrint
{
public://重载函数调用运算符 也称为仿函数void operator()(string test) //()代表了函数名 (string test) 形参列表{cout << test << endl;}
};void MyPrint02(string test)
{cout << test << endl;
}void test01()
{MyPrint myPrint;myPrint("hello world");//由于使用起来非常类似于函数调用,因此称为仿函数MyPrint02("hello world"); //函数调用
}//仿函数非常灵活 没有固定的写法 依照需求 写对应的仿函数
//加法类class MyAdd //实现两数相加
{
public:int operator()(int num1,int num2){return num1 + num2;}
};void test02()
{MyAdd myadd; //先创建对象int ret = myadd(100, 100);cout << "ret = " << ret << endl;//匿名对象调用 类型加小括号cout << "MyAdd()(100,100) = " << MyAdd()(100, 100) << endl;
}int main()
{test01();//test02();system("pause");return 0;
}
运算符重载函数的总结:
1、运算符重载函数的函数名必须为关键字operator加一个合法的运算符。在调用该函数时,将右操作数作为函数的实参。
2、当用类的成员函数实现运算符的重载时,运算符重载函数的参数(当为双目运算符时)为一个或(当为单目运算符时)没有。运算符的左操作数一定是对象,因为重载的运算符是该对象的成员函数,而右操作数是该函数的参数。
3、单目运算符“++”和“"存在前置与后置问题.
前置“++"格式为:
返回类型 类名::operator++(){......}
而后置“++"格式为:
返回类型 类名::operator++(int){......}
后置“++”中的参数int仅用作区分,并无实际意义,可以给一个变量名,也可以不给变量名。
4、C++中只有极少数的运算符不允许重载
重载运算符有以下几种限制:
不可臆造新的运算符.
不能改变运算符原有的优先级、结合性和语法结构,不能改变运算符操作数的个数.
运算符重载不宜使用过多
重载运算符含义必须清楚,不能有二义性
相关文章:

C++ :运算符重载
运算符重载: 运算符重载概念:对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型 运算符的重载实际是一种特殊的函数重载,必须定义一个函数,并告诉C编译器,当遇到该重载的运算符…...

如何跑通跨窗口渲染:multipleWindow3dScene
New 这是一个跨窗口渲染的示例,用 Three.js 和 localStorage 在同一源(同产品窗口)上跨窗口设置 3D 场景。而这也是本周推特和前端圈的一个热点,有不少人在争相模仿它的实现,如果你对跨窗口的渲染有兴趣,可…...

flutter-web中使用js工具类
文章目录 为什么要调用js1. flutter-web1. 引入js web/index.html2. 创建工具js web/CryptoEnc.js3. 创建对应的lib/js/js_interop.dart4. 由于引入的js是针对web平台的,所以引入需要做引入处理5. 使用 2. Android1. 引入依赖2. index.html3. dart引用 为什么要调用…...

@ResponseBody详解:用于响应体响应数据
RestFul风格或者是web阶段接触过的异步请求,都需要把数据转换成Json放入响应体中。 ResponseBody的作用其实是将java对象转为json格式的相应内容 使用 RequestMapping注解时,Spring会将返回值解析为视图路径,然后跳转路径返回对应的视图页面…...

【Python百练——第3练】矩形类及操作
💐作者:insist-- 💐个人主页:insist-- 的个人主页 理想主义的花,最终会盛开在浪漫主义的土壤里,我们的热情永远不会熄灭,在现实平凡中,我们终将上岸,阳光万里 ❤️欢迎点…...

【C语言学习疑难杂症】C语言中数组存储时为什么从低地址到高地址
在C语言中,数组的存储从低地址到高地址是有其历史原因的。这种设计主要是为了与计算机系统的内存组织方式相一致。 在计算机系统中,内存通常按照字节进行编址,地址从低到高递增。数组在内存中是连续存储的,因此数组的第一个元素&…...

Linux:查看端口占用的进程
命令 netstat -tunlp可以从图中看到,端口被那个进程占用,对应进程的pid是多少。...

医美店会员管理系统预约小程序作用是什么
医美在美业中占据着一定地位,爱美使然和经济独立、悦己消费下,不少女性会前往医美机构做脸部整容、嫩肤补水等服务,如美容院一样都是具备本地外地属性的,因此在如今互联网盛行下,商家需要借势线上破解难题及增强生意效…...

Linux 正则表达式
内容概述 1 文本编辑工具之神 VIM 1.1 vi 和 vim 简介 在 Linux 中我们经常编辑修改文本文件,即由 ASCII Unicode 或者其他编码的纯文字的文件。之前介绍过的 nano,实际工具中我们使用更为专业,功能强大的工具 文本编辑种类: vi…...

C语言面试之数组指针上篇
C语言数组是C语言中重要的数据结构之一,它用于存储一组相同类型的数据。数组在C语言中是以连续的内存空间来存储的,每个数组元素都是一个变量,占据一定的内存空间,数组元素之间是紧密相邻的。 一、数组的定义 在C语言中࿰…...

LinkWeChat,唯一以开源为核心的SCRM
LinkWeChat是国内首个基于企业微信的开源SCRM,在集成了企微强大的开放能力的基础上,进一步升级拓展灵活高效的客户运营能力及多元化精准营销能力,让客户与企业之间建立强链接,帮助企业提高客户运营效率,强化营销能力&a…...

Android textView 显示: STRING_TOO_LARGE
在Android中,字符串资源的长度限制是32KB,getString()方法返回的字符串资源的大小超过这个限制,就会抛出STRING_TOO_LARGE 这个错误。 我本地的临界值是:32.3 KB (33,090 字节) 小于等于33090时,能正常显示ÿ…...

用HeidiSQL在MySQL中创建新的数据库
用有权限的用户登录: 右键单击,选择: 输入要创建的数据库名称,然后点击“确定”: 刷新下,就看到新创建的数据库了: 在新创建的数据库中,就可以做其它操作了,例如…...

纯前端实现导入excel数据
准备工作 - 下载 xlsx npm install xlsx下面直接上代码👇 <template><div><input type"file" accept".xlsx, .xls" change"handleClick"></div> </template><script langts setup> import * a…...

Matlab下载许可证文件 教程(在账号有许可证的前提下)
文章目录 Part.I IntroductionPart.II 许可证文件过期解决方案Chap.I 使用 Internet 自动激活Chap.II 在不使用 Internet 的情况下手动激活 Part.I Introduction 本文主要介绍,在 Mathwork 账号有许可证的前提下,下载许可证的操作流程。 好久没有用 Mat…...

AI 绘画 | Stable Diffusion 电商模特
前言 上一篇文章讲到如何给人物更换背景和服装。今天主要讲电商模特,就是服装电商们的固定服装产品图片如何变成真人模特穿上的固定服装产品效果图。如果你掌握了 《AI 绘画 | Stable Diffusion 人物 换背景|换服装》,这篇文章对你来说,上手会更轻松。 教程 提取服装蒙版…...

vue面试题整理(1.0)
一、对MVC,MVP,MVVM的理解 三者都是项目的架构模式(不是类的设计模式),即:一个项目的结构,如何分层,不同层负责不同的职责。 1.MVC MVC的出现是用在后端(全栈时代&…...

PyQt基础_007_ 按钮类控件QCombox
import sys from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5.QtWidgets import *class ComboxDemo(QWidget):def __init__(self, parentNone):super(ComboxDemo, self).__init__(parent)self.setWindowTitle("combox 例子") self.resize(300, 90) …...

Android Wifi的扫描机制
Android Wifi 的扫描场景分为下面四种情况: 1.亮屏情况下,在Wifi settings界面,固定扫描,扫描时间为10s。 2.亮屏情况下,在非Wifi settings界面,二进制指数退避扫描,退避:interval…...

类 —— 友元、常/静态成员函数
类 类的大小 和结构体大小求法一致。但需注意,普通空类也会占用 1 字节大小,因为普通空类可以实例化对象。 而 抽象空类占 4 字节(32 位机中),因为抽象空类中含有虚指针(含有虚函数的非抽象空类同理&am…...

单页面应用
单页面应用 1.什么是SPA 多页面应用:每个页面都是独立的html文件,页面切换是整体刷新,需要重新加载html、css、JS等文件,容易实现搜索引擎,数据通过url、cookie、localStore传递。 单页面应用:多个页面是…...

六、ZooKeeper Java API操作
目录 1、引入maven坐标 2、节点的操作 这里操作Zookeeper的JavaAPI使用的是一套zookeeper客户端框架 Curator ,解决了很多Zookeeper客户端非常底层的细节开发工作 。 Curator包含了几个包:...

美甲美睫店预约会员管理小程序作用如何
美甲美睫是美业中较为重要的类目,主要以小摊、门店/连锁形式,随着线上化程度加深,传统线下美业店面临着困境,想要进一步增长及解决痛点,就需要线上数字化运营得到更多生意。 那么通过【雨科】平台搭建美甲美睫店小程序…...

Vue3为什么会推出组合式API
前言 大学前端入门学的vue2,工作了又用的React,现在想学习一下Vue3,开篇就介绍了组合式API,这和我认知里的vue2的选项式API区别还是蛮大的。本篇文章简单介绍一下组合式API。 什么是组合式API Vue 3引入了一种新的 API…...

windows11 phpstudy_pro php8.2 安装redis扩展
环境:windows11 phpstudy_pro php8.2.9 一、命令查看是否安装redis扩展 在对应网站中通过打开,,选择对应的PHP版本,用命令 php -m 查看自己的php 有没有redis扩展 上面如果有,说明已经安装了,如果没有安装࿱…...

中英双语大模型ChatGLM论文阅读笔记
论文传送门: [1] GLM: General Language Model Pretraining with Autoregressive Blank Infilling [2] Glm-130b: An open bilingual pre-trained model Github链接: THUDM/ChatGLM-6B 目录 笔记AbstractIntroductionThe design choices of GLM-130BThe …...

力扣题:字符串的反转-11.24
力扣题-11.24 [力扣刷题攻略] Re:从零开始的力扣刷题生活 力扣题1:151. 翻转字符串里的单词 解题思想:保存字符串中的单词即可 class Solution(object):def reverseWords(self, s):""":type s: str:rtype: str"&quo…...

NIO--07--Java lO模型详解
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 何为 IO?先从计算机结构的角度来解读一下I/o.再从应用程序的角度来解读一下I/O 阻塞/非阻塞/同步/异步IO阻塞IO非阻塞IO异步IO举例 Java中3种常见的IO模型BIO (Blo…...

OpenSSH 漏洞修复升级最新版本
Centos7系统ssh默认版本一般是OpenSSH7.4左右,低版本是有漏洞的而且是高危漏洞,在软件交付和安全扫描上是过不了关的,一般情况需要升级OpenSSH的最新版本 今天详细说下升级最新版本的处理过程(认真看会发现操作很简单,…...

【数据结构和算法】无限集中的最小数字
其他系列文章导航 Java基础合集 设计模式合集 多线程合集 分布式合集 ES合集 文章目录 其他系列文章导航 文章目录 前言 一、题目描述 二、题解 三、代码 四、总结 前言 这是力扣的2336题,难度为中等,解题方案有很多种,本文讲解我认为…...