浅谈C++|运算符重载


重载原因

C++ 中的运算符重载是一种特性,允许程序员定义自定义类类型的运算符操作。通过运算符重载,可以对类对象执行类似于内置类型的操作,例如加法、减法、乘法等。

运算符重载通过定义特定的成员函数或非成员函数来实现。成员函数的运算符重载为类的成员函数,且至少需要一个类对象作为操作数。而非成员函数的运算符重载则是独立于类的函数,其参数可以是类对象、指针或者引用。

运算符重载使用特定的语法,以便将运算符关联到相应的函数实现。例如,对于双目运算符(如+、-、*),可以通过重载成员函数或非成员函数的方式定义其操作。其中,成员函数的运算符重载使用成员函数的方式进行调用,而非成员函数的运算符重载则使用运算符的左侧对象作为第一个参数。

运算符重载提供了方便和直观的方式来执行类对象之间的操作。它可以使代码更具可读性,并提供更自然的语义,使得类的行为更接近内置类型。

然而,运算符重载也需要谨慎使用。过度使用运算符重载可能会导致代码可读性下降,使得代码难以理解和维护。因此,在进行运算符重载时,应注意遵循适当的语义和约定,并且避免使用过于复杂或混淆的运算符重载实现。

总结来说,C++ 中的运算符重载是一种强大的特性,允许程序员定义自定义类类型的运算符操作。通过合理和适度地使用运算符重载,可以提高代码的可读性和可维护性,使类对象的操作更加自然和直观。

一.加号运算符重载

对于内置的数据类型的表达式的运算符是不可能改变的

不要滥用运算符重载 

1.1成员函数实现

成员函数实现时,即使成员函数是私有变量,也是可以实现运算符重载的,并且支持函数重载。

代码: 

#include <iostream>
using namespace std;
class person {
friend void fun();
private:int age;int year;
public:person(int age, int year) :age(age), year(year) {}person(){}person operator+(person& p) {person m;m.age = this->age + p.age;m.year = this->year + p.year;return m;}
};
void fun() {person a(10, 90);person b(34, 89);person c = a + b;cout << c.age << ' ' << c.year << endl;
}
int main() {fun();return 0;
}

此时person c = a + b本质是person c=a.operator+(b);

person d = a + 10本质是person d=a.operator+(10);

 2.2全局函数实现

全局函数实现时,重载运算符函数不能直接访问私有成员变量,需要在类中声明友元。

代码: 

#include <iostream>
using namespace std;
class person {
friend void fun();   //设置全局函数是友元
friend person operator+(person& p1, person& p2);
friend person operator+(int p, person& p1);
private:int age;int year;
public:person(int age, int year) :age(age), year(year) {}person(){}
};person operator+(person& p1,person& p2) {person m;m.age =p1.age + p2.age;m.year =p1.age + p2.year;return m;
}person operator+(int p,person& p1) {   //函数重载person m;m.age = p1.age + p;m.year = p1.year + p;return m;
}
void fun() {person a(10, 90);person b(34, 89);person c = a + b;person d = 10+ a;  cout << c.age << ' ' << c.year << endl;cout << d.age << ' ' << d.year << endl;
}
int main() {fun();return 0;
}

此时,person c = a + b;  本质是person c =operator+(a,b);
           person d = 10+ a;  本质是person d =operator+(10,a);

 二.左移运算符重载

2.1成员函数实现

成员函数只能实现p<<cout......类型,cout不能放在左边;

 代码:

#include <iostream>
using namespace std;
class person {
private:int age;int year;
public:person(int age,int year):age(age),year(year){}person() {};//返回ostream&是为了链式调用ostream& operator<<(ostream& cout) {cout << this->age << ' ' << this->year;return cout;}
};
void fun() {person p(23,78);p << cout << "成功" << endl;//本质p.operator<<(cout)<<"成功"<<endl;
}
int main() {fun();return 0;
}

p << cout << "成功" << endl的本质是p.operator<<(cout)<<"成功"<<endl;

 2.2全局函数实现

全局函数可以实现cout在类的左边,也可以实现在类的右边

代码:

#include <iostream>
using namespace std;
class person {
friend ostream& operator<<(ostream& cout, person& p);
private:int age;int year;
public:person(int age, int year) :age(age), year(year) {}person() {};//返回ostream&是为了链式调用
};
ostream& operator<<(ostream& cout,person& p) {cout << p.age << ' ' << p.year;return cout;
}
void fun() {person p(23, 78);cout<< p << "成功" << endl;//本质p.operator<<(cout)<<"成功"<<endl;//本质operator<<(cout,p)<<"成功"<<endl;
}
int main() {fun();return 0;
}

三.++运算符重载

前置++重载不用参数,返回值是引用类型,后置++重载要int占位参数,返回值是值。

 31.前置++

代码: 

#include <iostream>
using namespace std;
class myint {
friend ostream& operator<<(ostream& cout, myint& p);
public:myint(int age,int year):age(age),year(year){}myint(){}//重载前置++,返回*this也是为了链式调用myint& operator++() {this->age++;return *this;}
private:int age;int year;
};
//重载<<运算符,注意是ostream& cout,是引用类型
ostream& operator<<(ostream& cout, myint &p) {cout << p.age << ' ' << p.year;return cout;
}
void fun() {myint p(10, 20);cout << ++(++p) << endl;;
}
int main() {fun();return 0;
}

 返回追是引用类型,如果返回普通值的话,只能自增一次,第二次只是改变副本。

3.2后置 ++

代码:

#include <iostream>
using namespace std;
class myint {
friend ostream& operator<<(ostream& cout, myint& p);
friend void fun1();
public:myint(int age,int year):age(age),year(year){}myint(){}//重载前置++,返回*this也是为了链式调用myint& operator++() {this->age++;return *this;}//重置后置++,返回之前副本。myint operator++(int) {myint m = *this;this->age++;return m;}
private:int age;int year;
};
//重载<<运算符,注意是ostream& cout,是引用类型
ostream& operator<<(ostream& cout, myint &p) {cout << p.age << ' ' << p.year;return cout;
}
void fun() {myint p(10, 20);cout << ++(++p)<<endl;;
}
void fun1() {myint p(10, 20);cout << (p++).age << endl;cout << p.age << endl;
}
int main() {fun1();return 0;
}

后置++用int占位参数,用来区分和前置++的区别,并且要注意,返回的是值类型

 四.赋值运算符重载

 在实例化类的对象时,会自动创建一个operator=函数,不过此时是浅拷贝,当遇到建立到堆上的数据类型时。调用赋值运算符会报错。此时需要重载赋值运算符,将浅拷贝改为深拷贝。

代码:

#include <iostream>
using namespace std;
class person {
public:int* age;int year;//有参构造,在堆区开辟person(int age, int year) {this->age = new int(age);this->year = year;}//深拷贝person(const person& p) {year = p.year;age = new int(*p.age);}//返回值是引用类型,链式调用person& operator=(const person& p) {if (this->age != NULL) {delete age;age = NULL;}year = p.year;//深拷贝age = new int(*p.age);   return *this;}~person() {if (this->age != NULL) {delete age;age = NULL;}}
};
void fun() {person p1(43, 78);person p2(4, 7);person p3(89, 90);p3=p2 = p1;cout << *p2.age << ' ' << p2.year << endl;cout << *p3.age << ' ' << p3.year << endl;
}
int main() {fun();return 0;
}

p3=p2 = p1的本质是p3.operator=(p2.operator=(p1))

 五.函数调用运算符重载

·函数调用运算符()也可以重载

·由于重载后使用的方式非常像函数的调用,因此称为仿函数,仿函数没有固定写法,非常灵活

 代码:


#include <iostream>
using namespace std;
class person {
public:int age;person(int age) {this->age = age;}person(){}void operator()(string name) {cout << name << endl;}void operator()() {cout << "年龄是:" << age << endl;}
};
void fun() {person p1(10);person p2(20);p1("name_name");//匿名对象person()("匿名调用");p1();p2();
}
int main() {fun();return 0;
}

六.关系运算符重载

作用:重载关系运算符,可以让两个自定义类型对象进行对比操作

 代码:

#include <iostream>
using namespace std;
class person {
public:int age;string name;person(int age, string name) :age(age), name(name) {}//重载==号,函数设置为常函数是为了防止误操作bool operator==(const person& p)  const{if (age == p.age && name == p.name) {return true;}return false;}//重载!=号bool operator!=(const person& p) const  {if (age == p.age && name == p.name) {return false;}return true;}//重载>号bool operator>(const person& p) const {if (age == p.age) {return name > p.name;}else {return age > p.age;}}};
void fun() {person p1(40, "tom");person p2(10, "aom");if (p1 == p2) {cout << "p1=p2" << endl;}else {cout << "p1!=p2" << endl;}if (p1 != p2) {cout << "p1!=p2" << endl;}else {cout << "p1==p2" << endl;}if (p1 > p2) {cout << "p1 > p2" << endl;}else {cout << "p1 <= p2" << endl;}
}
int main() {fun();return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/82634.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PyG-GAT-Cora(在Cora数据集上应用GAT做节点分类)

文章目录 model.pymain.py参数设置运行图 model.py import torch.nn as nn from torch_geometric.nn import GATConv import torch.nn.functional as F class gat_cls(nn.Module):def __init__(self,in_dim,hid_dim,out_dim,dropout_size0.5):super(gat_cls,self).__init__()s…

java学习--day6(数组)

文章目录 day5作业今天的内容1.数组1.1开发中为啥要有数组1.2在Java中如何定义数组1.3对第二种声明方式进行赋值1.4对数组进行取值1.5二维数组【了解】1.6数组可以当成一个方法的参数【重点】1.7数组可以当成一个方法的返回值1.8数组在内存中如何分配的【了解】 2.数组方法循环…

PFEA111–20 PFEA111–20 人工智能如何颠覆石油和天然气行业

PFEA111–20 PFEA111–20 人工智能如何颠覆石油和天然气行业 人工智能(AI)和机器学习(ML)等新技术的到来正在改变几十年来行业的运营方式。这些技术正在带来革命性的变革&#xff0c;影响着整个行业。石油和天然气行业在其运营过程中面临着许多挑战&#xff0c;如未连接的环境…

在SpringBoot项目中整合SpringSession,基于Redis实现对Session的管理和事件监听

1、SpringSession简介 SpringSession是基于Spring框架的Session管理解决方案。它基于标准的Servlet容器API&#xff0c;提供了Session的分布式管理解决方案&#xff0c;支持把Session存储在多种场景下&#xff0c;比如内存、MongoDB、Redis等&#xff0c;并且能够快速集成到Spr…

Java21 LTS版本

一、前言 除了众所周知的 JEP 之外&#xff0c;Java 21 还有更多内容。首先请确认 java 版本&#xff1a; $ java -version openjdk version "21" 2023-09-19 OpenJDK Runtime Environment (build 2135-2513) OpenJDK 64-Bit Server VM (build 2135-2513, mixed mo…

activiti7的数据表和字段的解释

activiti7的数据表和字段的解释 activiti7版本有25张表&#xff0c;而activiti6有28张表&#xff0c;activiti5有27张表&#xff0c;绝大部分的表和字段的含义都是一样的&#xff0c;所以本次整理的activiti7数据表和字段的解释&#xff0c;也同样适用于activiti6和5。 1、总览…

pcl--第五节 点云表面法线估算

估算点云表面法线 * 表面法线是几何表面的重要属性&#xff0c;在许多领域&#xff08;例如计算机图形应用程序&#xff09;中大量使用&#xff0c;以应用正确的光源以产生阴影和其他视觉效果。 给定一个几何表面&#xff0c;通常很难将表面某个点的法线方向推断为垂直于该点…

CockroachDB集群部署

CockroachDB集群部署 1、CockroachDB简介 CockroachDB(有时简称为CRDB)是一个免费的、开源的分布式 SQL 数据库&#xff0c;它建立在一个事务性和强一致性的键 值存储之上。它由 PebbleDB(一个受 RocksDB/leveldb 启发的 K/B 存储库)支持&#xff0c;并使用 Raft 分布式共识…

TypeScript入门

目录 一&#xff1a;语言特性 二&#xff1a;TypeScript安装 NPM 安装 TypeScript 三&#xff1a;TypeScript基础语法 第一个 TypeScript 程序 四&#xff1a;TypeScript 保留关键字 空白和换行 TypeScript 区分大小写 TypeScript 注释 TypeScript 支持两种类型的注释 …

初识C语言——详细入门一(系统性学习day4)

目录 前言 一、C语言简单介绍、特点、基本构成 简单介绍&#xff1a; 特点&#xff1a; 基本构成&#xff1a; 二、认识C语言程序 标准格式&#xff1a; 简单C程序&#xff1a; 三、基本构成分类详细介绍 &#xff08;1&#xff09;关键字 &#xff08;2&#xf…

fork函数

二.fork函数 2.1函数原型 fork()函数在 C 语言中的原型如下&#xff1a; #include <unistd.h>pid_t fork(void);其中pid_t是一个整型数据类型&#xff0c;用于表示进程ID。fork()函数返回值是一个pid_t类型的值&#xff0c;具体含义如下&#xff1a; 如果调用fork()的…

MyBatis中当实体类中的属性名和表中的字段名不一样,怎么办

方法1&#xff1a; 在mybatis核心配置文件中指定&#xff0c;springboot加载mybatis核心配置文件 springboot项目的一个特点就是0配置&#xff0c;本来就省掉了mybatis的核心配置文件&#xff0c;现在又加回去算什么事&#xff0c;总之这种方式可行但没人这样用 具体操作&…

Python灰帽编程——错误异常处理与面向对象

文章目录 错误异常处理与面向对象1. 错误和异常1.1 基本概念1.1.1 Python 异常 1.2 检测&#xff08;捕获&#xff09;异常1.2.1 try except 语句1.2.2 捕获多种异常1.2.3 捕获所有异常 1.3 处理异常1.4 特殊场景1.4.1 with 语句 1.5 脚本完善 2. 内网主机存活检测程序2.1 scap…

【Java 基础篇】Java字符打印流详解:文本数据的输出利器

在Java编程中&#xff0c;我们经常需要将数据输出到文件或其他输出源中。Java提供了多种输出流来帮助我们完成这项任务&#xff0c;其中字符打印流是一个非常有用的工具。本文将详细介绍Java字符打印流的用法&#xff0c;以及如何在实际编程中充分利用它。 什么是字符打印流&a…

DNG格式详解,DNG是什么?为何DNG可以取代RAW统一单反相机、苹果安卓移动端相机拍摄输出原始图像数据标准

返回图像处理总目录&#xff1a;《JavaCV图像处理合集总目录》 前言 在DNG格式发布之前&#xff0c;我们先了解一下之前单反相机、苹果和安卓移动端相机拍照输出未经处理的原始图像格式是什么&#xff1f; RAW 什么是RAW&#xff1f; RAW是未经处理、也未经压缩的格式。可以…

Rust通用编程概念(3)

Rust通用编程概念 1.变量和可变性1.执行cargo run2.变量3.变量的可变性4.常量5.遮蔽5.1遮蔽与mut区别1.遮蔽2.mut 2.数据类型1.标量类型1.1整数类型1.2浮点数类型1.3数字运算1.4布尔类型1.5字符类型 2.复合类型2.1元组类型2.2数组类型1.访问数组2.无效的数组元素访问 3.函数3.1…

如何解决 503 Service Temporarily Unavailable?

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f405;&#x1f43e;猫头虎建议程序员必备技术栈一览表&#x1f4d6;&#xff1a; &#x1f6e0;️ 全栈技术 Full Stack: &#x1f4da…

想要精通算法和SQL的成长之路 - 填充书架

想要精通算法和SQL的成长之路 - 填充书架 前言一. 填充书架1.1 优化 前言 想要精通算法和SQL的成长之路 - 系列导航 一. 填充书架 原题链接 题目中有一个值得注意的点就是&#xff1a; 需要按照书本顺序摆放。每一层当中&#xff0c;只要厚度不够了&#xff0c;当前层最高…

【考研数学】高等数学第六模块 —— 空间解析几何(1,向量基本概念与运算)

文章目录 引言一、空间解析几何的理论1.1 基本概念1.2 向量的运算 写在最后 引言 我自认空间想象能力较差&#xff0c;所以当初学这个很吃力。希望现在再接触&#xff0c;能好点。 一、空间解析几何的理论 1.1 基本概念 1.向量 —— 既有大小&#xff0c;又有方向的量称为向…

C语言指针,深度长文全面讲解

指针对于C来说太重要。然而&#xff0c;想要全面理解指针&#xff0c;除了要对C语言有熟练的掌握外&#xff0c;还要有计算机硬件以及操作系统等方方面面的基本知识。所以本文尽可能的通过一篇文章完全讲解指针。 为什么需要指针&#xff1f; 指针解决了一些编程中基本的问题。…