首页 > 编程语言 >C++学习日记---第18天(5k字 重载运算符快速通关)

C++学习日记---第18天(5k字 重载运算符快速通关)

时间:2024-12-05 20:04:24浏览次数:5  
标签:--- p1 int 18 operator 运算符 person 重载

(本文包含了从基础到中等的运算符重载内容,以及一些在编写代码时可能遇到的问题)


 

笔记复习

1.运算符重载

以代码实现一个类的两个对象相加为例

#include<iostream>
using namespace std;

class person {
	int m_deposit = 1000;
	int income = 100;
};

int main() {
	person p1;
	person p2;
	person p3 = p1 + p2;
	return 0;
}

我们想要实现p1的m_deposit与p2的m_deposit相加成为p3的m_deposit,p1的income与p2的income相加成为p3的income,但是这时候编译器会提示我们没有与这些操作数匹配的“+”运算符,这个时候就需要重载运算符

可以对已有的运算符重新进行定义,赋予其另外一种功能,以适应不同数据类型

运算符重载实际上是一种特殊的函数重载,我们定义一个函数实现与指定运算符相似但不同的功能,当我们调用这个运算符时转为调用该函数

1)加号运算符重载

作用:实现两个自定义数据类型相加的运算

a.成员函数重载加号运算符

语法:在class内部

类名 operator+(只能接收一个对象的地址){};

ps:因为加号运算符是二元运算符,所以只能对两个数据进行操作,这里类的对象拥有这个函数作为一个数据,传入的对象作为一个数据

#include<iostream>
using namespace std;

class person {
public:
	person operator+(person& p) {
		person temp;
		temp.m_deposit = m_deposit + p.m_deposit;
		temp.m_income = m_income + p.m_income;
		return temp;
	}
	int m_deposit = 1000;
	int m_income = 100;
};

int main() {
	person p1;
	person p2;
	person p3 = p1+p2;
//成员函数重载本质上是
//person p3=p1.operator+(p2);或person p3.operator+(p1);
	cout << p3.m_deposit << endl;
	cout << p3.m_income << endl;
	return 0;
}

b.全局函数实现加号运算符重载

#include<iostream>
using namespace std;

class person {
public:
	int m_deposit = 1000;
	int m_income = 100;
};

person operator+(person& p1, person& p2) {
	person temp;
	temp.m_deposit = p1.m_deposit + p2.m_deposit;
	temp.m_income = p1.m_income + p2.m_income;
	return temp;
}

int main() {
	person p1;
	person p2;
	person p3 =p1+p2;
//全局函数重载本质上是
//person p3=operator+(p1,p2);
	cout << p3.m_deposit << endl;
	cout << p3.m_income << endl;
	return 0;
}

通过上面的两个例子我们可以知道,重载加号运算符实现两个对象进行相加的操作实际上创建一个函数,在这个函数中创建一个对象,实现这个两个的数据分别对应相加,然后返回这个对象给p3,于是就实现了加号运算符重载,所以运算符重载本质上就是自定义函数的调用

减号运算符重载与加号运算符重载是一样的,两者都是二元运算符,大家可以自己尝试一下

2)左移运算符重载

<<称为左移运算符

语法:

void operator<<(ostream& cout,另一个形参){}

作用:可以自定义输出数据类型

左移运算符是二元运算符,需要两个操作数,一个作为左操作数,一个作为右操作数,而在类中时,类的对象会作为左操作数,但我们要求cout在左边,类的对象在右边,因此无法在使用成员函数重载左移运算符

全局函数重载左移运算符

#include<iostream>
using namespace std;

class person {
public:
	int m_deposit = 1000;
	int m_income = 100;
};

ostream& operator<<(ostream& cout,person& p) {
	cout << p.m_deposit << endl;
	cout << p.m_income << endl;
	return cout;
}
//使用ostream&可以支持链式调用,当 << 操作完成后,返回输出流对象,这样可以继续使用 <<
//person& p,引用传递,p 是一个引用,使用引用而不是传值,可以避免拷贝整个对象,提高效率。


int main() {
	person p1;
	cout << p1;
	return 0;
}

3)递增运算符重载

作用:通过重载递增运算符,实现自己的整型数据

a.前置递增运算符与后置递增运算符的区别

前置递增运算符是先执行递增操作,再返回递增后的值;后置递增运算符是先保存当前值,再执行递增操作,然后返回递增前的值。通俗来说就是前置递增运算符先递增再执行其他语句,后置递增运算符先执行其他语句再递增。

代码示例:

后置递增运算符

#include<iostream>
using namespace std;

int main() {
	int a = 0;
	cout << a++ << endl;
	cout << a << endl;
	return 0;
}

a702c4525e39413e878c1f7b8adc6adc.png

前置递增运算符:

#include<iostream>
using namespace std;

int main() {
	int a = 0;
	cout << ++a << endl;
	cout << a << endl;
	return 0;
}

56a4f8a6acfd4a7c9ba3c2a2ab822b9c.png 

b.后置递增运算符重载

#include<iostream>
using namespace std;

class myinteger {
public:
	myinteger() {
		m_num = 0;
	}
	myinteger operator++(int) {
	//int用来表明是后置递增,无实际作用
		myinteger temp = *this;
		m_num++;
		return temp;
	}
private:
	int m_num;
};

void test01() {
	myinteger myint;
	myint++;
}

int main() {
	test01();
	system("pause");
	return 0;
}

 接下来我们试着输出一下我们的整型,注意,这里并不是真正的整型,因此我们需要重载左移运算符。

ostream& operator<<(ostream& cout, myinteger myint) {
	cout << myint.m_num;
//由于后置递增运算符返回的是m_num,因此我们这里要输出myint.m_num
	return cout;
}

由于重载左移运算符的函数访问了myinteger类的私有成员,因此要在类中进行一次友元声明,完整代码如下:

#include<iostream>
using namespace std;

class myinteger {
	friend ostream& operator<<(ostream& cout, myinteger myint);
public:
	myinteger() {
		m_num = 0;
	}
	myinteger operator++(int) {
	//int用来表明是后置递增,无实际作用
		myinteger temp = *this;
		m_num++;
		return temp;
	}
private:
	int m_num;
};

ostream& operator<<(ostream& cout, myinteger myint) {
	cout << myint.m_num;
	return cout;
}

void test01() {
	myinteger myint;
	myint++;
}

int main() {
	test01();
	system("pause");
	return 0;
}

c.重载前置递增运算符

基本等同于重载后置递增运算符,区别在于重载前置递增运算符时不需要用int占位参数

#include<iostream>
using namespace std;

class myinteger {
	friend ostream& operator<<(ostream& cout, myinteger myint);
public:
	myinteger operator++() {
		++deposit;
		myinteger temp = *this;
		return *this;
	}
private:
	int deposit = 999;
};

ostream& operator<<(ostream& cout , myinteger myint) {
	cout << myint.deposit;
	return cout;
}

int main() {
	myinteger myint;
	cout << ++myint << endl;;
	return 0;
}

4)递减运算符重载

类同于递增运算符,大家自己操作即可

5)关系运算符重载

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

案例讲解:一个类中有成员name和age,如果两个对象的name和age相同,那么我们称这两个对象相等,下面用代码实现两个对象的比较

对于关系运算符,返回值为true或者false,因此我们的函数类型应设置为bool

#include<iostream>
using namespace std;

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) {
	//这里this指针用来解决名称重复问题
    //这里this指向的是调用operator==左侧的对象,p是右侧对象,作为参数传入
			return true;
		}
		return false;
	}
private:
	string m_name;
	int m_age;
};

void test01() {
	person p1("tom", 18);
	person p2("tom", 18);
	if (p1 == p2) {
//p1在==左边,因此this指向p1
		cout << "p1和p2是相等的" << endl;
	}
	else {
		cout << "p1和p2是不相等的" << endl;
	}
}

int main() {
	test01();
	system("pause");
	return 0;
}

6)函数调用运算符重载

#include<iostream>
#include<string>
using namespace std;

class myprint {
public:
	void operator()(string test) {
		cout << test << endl;
	}
};

void test01() {
	myprint myprint;
	myprint("hello world");
//实质上是myprint.operator("hello world")
//重载函数调用运算符可以使类对象像函数一样被调用,由于使用起来非常类似于函数调用,因此称为仿函数
}

int main() {
	test01();
	system("pause");
	return 0;
}

仿函数非常灵活,没有固定写法,理论上只要是函数调用能干的事仿函数都可以干,下面我们来看另一个例子,仿函数实现两数相加

#include<iostream>
#include<string>
using namespace std;

class myadd {
public:
	int operator()(int num1, int num2) {
		return num1 + num2;
	}
};

void test02() {
	myadd k;
	cout << k(100, 100) << endl;
}

int main() {
	test02();
	system("pause");
	return 0;
}

 

 

标签:---,p1,int,18,operator,运算符,person,重载
From: https://blog.csdn.net/wlyyywwq/article/details/144206645

相关文章

  • C++算法练习-day62——491.非递减子序列
    题目来源:.-力扣(LeetCode)题目思路分析这个问题要求找出数组 nums 中的所有非严格递增子序列,其中每个子序列至少包含两个元素。非严格递增子序列意味着子序列中的元素可以相等,但不允许递减。为了解决这个问题,可以使用回溯法。回溯法是一种通过探索所有可能的候选解来找出......
  • C++算法练习-day61——90.子集2
    题目来源:.-力扣(LeetCode)题目思路分析题目要求找出给定数组的所有子集(幂集),但数组可能包含重复元素,要求结果中的子集是唯一的(不包含重复的子集)。为了解决这个问题,我们可以先对数组进行排序,然后在回溯过程中跳过重复的元素,以确保生成的每个子集都是唯一的。代码:#include<v......
  • C++算法练习-day60——78.子集问题
    题目来源:.-力扣(LeetCode)题目思路分析题目要求找出给定数组的所有子集(幂集)。子集是指原数组中任意元素组合形成的数组,包括空集和原数组本身。这个问题可以通过回溯算法(Backtracking)来解决。回溯算法是一种通过探索所有可能的候选解来找出所有解的算法。对于子集问题,我们可以......
  • 靶场奇妙记之Kioptrix-Level1
    公众号:泷羽Sec-Ceo声明!        学习视频来自B站up主**泷羽sec**有兴趣的师傅可以关注一下,如涉及侵权马上删除文章,笔记只是方便各位师傅的学习和探讨,文章所提到的网站以及内容,只做学习交流,其他均与本人以及泷羽sec团队无关,切勿触碰法律底线,否则后果自负!!!!有兴趣的......
  • CCF认证-202409-03 | 补丁应用(未通过)
    前言:    这道题难度过于夸张?并且根据过往的CCFCSP认证第三题的通过率,我就没奔着通过去写,只是想测试一下定时1小时能摸到几分。这道题用时1小时28分钟(带完善),分数0。        所以CCF认证时在没有走投无路或者有80%以上把握就千万不能做这道题,第四题都比这个要......
  • CCF认证-202104-02 | 领域均值
    顿顿在学习了数字图像处理后,想要对手上的一副灰度图像进行降噪处理。不过该图像仅在较暗区域有很多噪点,如果贸然对全图进行降噪,会在抹去噪点的同时也模糊了原有图像。因此顿顿打算先使用邻域均值来判断一个像素是否处于较暗区域,然后仅对处于较暗区域的像素进行降噪处理。待......
  • H5-30 CSS3 新特性
    1、圆角使用CSS3border-radius属性,你可以给任何元素制作“圆角”border-radius属性,可以使用以下规则:①四个值:第一个值为左上角,第二个值为右上角,第三个值为右下角,第四个值为左下角②三个值:第一个值为左上角,第二个值为右上角和左下角,第三个值为右下角③......
  • rt-thread学习之路第四十九章--组件之FAL flash抽象层
    FAL组件FAL:Flash抽象层。在V4.1.0中,将fal软件包重新定义为RT-Thread内部组件,在使用方式上和以前有这些区别:(1)原本使用fal需要在RT-Thread的包管理器中选择并进行下载;(2)现在只需要在组件中打开使用即可,以下做详细介绍。1、FAL介绍FAL(FlashAbstractionLayer)F......
  • [原创]CEEMDAN-FTTA-CNN-BiLSTM足球队训练算法FTTA是多变量回归预测 (多输入单输出) M
    [原创]CEEMDAN-FTTA-CNN-BiLSTM足球队训练算法FTTA是多变量回归预测(多输入单输出)Matlab代码目录[原创]CEEMDAN-FTTA-CNN-BiLSTM足球队训练算法FTTA是多变量回归预测(多输入单输出)Matlab代码预测结果评价指标基本介绍程序设计参考资料预测结果评价指标......
  • Intel 的 Control-flow Enforcement Technology (CET) 是一项硬件级的安全技术,旨在增
    Intel的Control-flowEnforcementTechnology(CET)是一项硬件级的安全技术,旨在增强程序控制流的保护,防止攻击者利用控制流劫持(如ROP(Return-OrientedProgramming)和JOP(Jump-OrientedProgramming)等技术)来绕过传统的防护机制(如DEP和ASLR)。CET通过对程序的控制流进行严格......