IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++学习笔记:运算符重载 -> 正文阅读

[C++知识库]C++学习笔记:运算符重载


在编程过程中,有时希望使对象也能够通过运算符进行运算,可以使得代码更加容易理解,比如说数学上复数的+、-运算,但C++中,无法对两个复数对象直接应用+或-运算符。
我们希望能够写出 Complex_a + Complex_b 这样的语句。

定义

运算符重载,就是对已有的(C++中预定义好的)运算符赋予多重的含义,使对同一运算符作用于不同类型的数据时导致不同类型的行为。

也就是说,对于同一个运算符,针对不同类型的操作数,所发生的的行为也就不同。

运算符的重载,其实质上是函数重载。

在使用过程中,能够将含运算符的表达式转换成对运算符函数的调用,在此同时,将运算符的操作数转换成运算符函数的参数。

其形式,如下所示:

返回值类型 operator 运算符(形参表)
{
	……
}

目的

拓展C++ 中提供的运算符的适用范围,使之能够作用于对象。

性质说明

关于运算符的重载,其实质上是函数的重载,可以重载为普通的函数,也可以重载为类的成员函数。

当重载为普通函数时,函数的参数个数是运算符目数;
当重载为成员函数时,函数的参数个数是运算符目数减一。


至于这样性质的产生原因,我们在以下的实例中做出解释:

class Complex
{
	public:
		double real, imag;
		// 这是一个构造函数
		// 默认参数r,i均为0.0,分别为real和imag赋值
		Complex (double r=0.0, double i=0.0):real(r),imag(i) {  }
		
		// 作为类的成员函数的运算符重载
		// 返回值为Complex
		// 参数个数为运算符目数减一
		Complex operate - (const Complex &c);
};
// 作为普通函数的运算符重载
// 返回值为Complex
//参数个数为运算符目数
Complex operate + (const Complex &a, const Complex &b)
{
	return Complex(a.real+ b.real, a.imag+ b.imag);
}
// 
Complex Complex::operate - (const Complex & c)
{
	return Complex(real- c.real, imag- c.imag);
}

int main()
{
	Complex a(4,4), b(1,1), c;
	c = a+ b // 等价于 c = operator+(a,b)
	std::cout<< c.real<< ","<< c.imag<< std::endl; 
	std::cout<< (a-b).real<< ","<< (a-b).imag<< endl; // 等价于a.operator-(b)
	return 0;
}
/*输出
5,5
3,3
*/

至于为什么作为普通函数的运算符重载的参数为运算符目数,作为成员函数的运算符重载参数为运算符目数减一:
(1)c = a+ b语句等价于c = operator+(a,b),a+b 的地位是函数返回的一个临时变量,用后及删。无需对a+b中任何元素作保存的必要

(2)而(a- b).real 语句等价于a.operator-(b).real,后续读取real的操作,(或者说为了方便后续使用类内其他函数),就要求了a-b的返回值必须继续存储在a中,故而传入的参数仅为b一个(即运算符目数减一),而a作为operator-()调用的对象存在,在调用后存储a-b的结果。


赋值运算符的重载

在有些时候,我们希望赋值运算符量变的类型可以不是匹配的,比如将一个char * 类型的字符串赋值给一个字符串对象,这时就需要重载赋值运算符“=”了。

注: 赋值运算符“=” 只能重载为成员函数。

class String{
	private:
		char * str;
	public:
		//构造函数
		//首先将str指针指向一个char *长度的地址
		//然后将该地址赋值为0
		String ():str(new char[1]){ str[0]= 0;}
		const char * c_str() { return str;};
		String & operator = (const char * s);
		~String() {	delete [] str;}
};
String & String::operator=(const char * s)
{
	delete [] str;
	str = new char[strlen(s)+1];
	strcpy( str,s);
	return * this;//注:this为指针,*this指代为一个String类
}
int main()
{
	String s;
	s = "Good Luck,"; 
	// 等价于s.operator=("Good Luck,")
	// 若无等号的重载,则视为预定义的赋值语句,但s为String类的对象,等号右边为字符串,出错
	// 在本指令中,调用s.operator=(),将s中的str重新赋值,指向"Good Luck,"
	cout<< s.c_str() <<endl;
	s = "Shenzhou 8!";// 等价于 s.operator=("Shenzhou 8!");
	cout << s.c_str() << endl;
	return 0;
}
/*输出
Good Luck,
Shenzhou 8!
*/

------------------------华丽分割线---------------------------------
对于赋值运算符的重载,上述例子中是class = char类型的重载,如果是应用于以下情况呢?

String s;
s = "Hello";
s = s; // 或者换成String & s_copy = s;

我们仿之前实例中的一段代码进行修改,这时候就出现了一些问题。
以下是原代码:
在这里插入图片描述
修改过后:

String & String::operator=(const String & s)
{
	delete [] str;
	str = new char[strlen(s.str)+1];
	strcpy( str,s.str);
	return * this;//注:this为指针,*this指代为一个String类

发现并不能满足上述s=s 的使用需求:重载函数会将 s.str 删掉,这样就没有办法再为等号左边的s进行赋值了。于是再做修改:

String & String::operator=(const String & s)
{
	if (this == &s)
		return *this;
	delete [] str;
	str = new char[strlen(s.str)+1];
	strcpy( str,s.str);
	return * this;//注:this为指针,*this指代为一个String类

-----------------------------再度分割-----------------------------------
这样就莫得问题了嘛,大抵还是有的。

由于“=”比较特殊,在为String类编写复制构造函数时,会产生一个问题,我们先将修改结果进行展示:

String (String & s)
{
	str == new char[strlen(s.str)+1];
	strcpy(str , s.str);
}

下面展示默认构造函数的问题,先来看operate = 的返回值类型,我们发现实例中的返回值均为String &,那么为什么不用void或者String呢???

事实上,在C++预定义的“=”中,其返回值是为等号左边变量的引用。例如整型a=3,b=5,在a=b后返回的值为a的新值5
对于a=b=c;和(a=b)=c;
分别等价于a.operator = (b.operator = ( c ));
(a.operator=(b)).operator=( c );
“=”的运算结果为等号左边的变量的引用
对运算符进行重载的时候,好的风格是应该尽量保留运算符原本的特性

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-08-17 15:11:24  更:2021-08-17 15:11:58 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/26 16:07:53-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计