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++知识库 -> Cukor丘克说C++进阶02(下) 2021-08-18 -> 正文阅读

[C++知识库]Cukor丘克说C++进阶02(下) 2021-08-18

C++运算符重载(下)

C++运算符特殊重载

自增(++)、自减(–)的重载

关键在于前置和后置的区别

后置的 ‘++’ 或 ‘–’ 在写重载的时候需要一个无用的参数来标识

直接上代码吧

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

class MM
{
public:
	MM(string name,int faceScore):name(name),faceScore(faceScore){}
	MM operator++(int);		//重载后置++需要一个无用参数作为标识
	MM operator++();		//重载前置++不需要参数
	string& getName();
	int& getFaceScore();	//重载后置--需要一个无用参数作为标识
	MM operator--(int);		//重载前置--不需要参数
	MM operator--();
protected:
	string name;
	int faceScore;
};

int main()
{
	MM mm1("Alice", 100);
	MM mm2("Coco", 80);
	MM temp("", 0);
	temp = mm1++;
	cout <<"temp:"<< temp.getName() << '\t' << temp.getFaceScore() << endl;
	cout <<"mm1:"<< mm1.getName() << '\t' << mm1.getFaceScore() << endl;
	/*
	* 输出结果:
		temp:Alice      100
		mm1:Alice       101
	*/
	cout << "---------------------------------" << endl;
	temp = ++mm2;
	cout << "temp:" << temp.getName() << '\t' << temp.getFaceScore() << endl;
	cout << "mm2:" << mm2.getName() << '\t' << mm2.getFaceScore() << endl;
	/*
	* 输出结果:
		temp:Coco       81
		mm2:Coco        81
	*/
	cout << "--------------------------------" << endl;
	temp = mm2--;
	cout << "temp:" << temp.getName() << '\t' << temp.getFaceScore() << endl;
	cout << "mm2:" << mm2.getName() << '\t' << mm2.getFaceScore() << endl;
	/*
	* 输出结果:
		temp:Coco       81
		mm2:Coco        80
	*/
	cout << "--------------------------------" << endl;
	temp = --mm1;
	cout << "temp:" << temp.getName() << '\t' << temp.getFaceScore() << endl;
	cout << "mm1:" << mm1.getName() << '\t' << mm1.getFaceScore() << endl;
	/*
	* 输出结果:
		temp:Alice      100
		mm1:Alice       100
	*/
	return 0;
}

MM MM::operator++(int)
{
	//姓名就不做++运算了,只有颜值做++运算
	return MM(this->name,this->faceScore++);
}

MM MM::operator++()
{
	//姓名就不做++运算了,只有颜值做++运算
	return MM(this->name,++this->faceScore);
}

string& MM::getName()
{
	return this->name;
}

int& MM::getFaceScore()
{
	return this->faceScore;
}

MM MM::operator--(int)
{
	//名字不做运算,颜值做运算
	return MM(this->name,this->faceScore--);
}

MM MM::operator--()
{
	//名字不做运算,颜值做运算
	return MM(this->name,--this->faceScore);
}

C++运算符流重载

输入流和输出流只能直接操作基本数据类型,但无法直接操作自定义类型(类或结构体),所以现在想直接使用输入流和输出流直接操作自定义类型的必须要对运算符进行重载。

声明:

  • ostream和istream是类。
  • 在重载函数传参的时候,如果想改变对象里面的数据就采用引用传参,如果不行改变对象里面的数据可以普通传参,也可以采用引用传参。

重载下面的运算符:

  • <<
  • >>

先采用类的成员函数重载方式重载

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

class MM
{
public:
	//使用缺省的方式写构造函数
	MM(string name="Alice",int faceScore=100):name(name),faceScore(faceScore){}
	//重载输出
	ostream& operator<<(ostream& out);
	//重载输出
	istream& operator>>(istream& in);
protected:
	string name;
	int faceScore;
};

int main()
{
	MM mm;
	mm.operator<<(cout);
	cout << "请输入MM的姓名和颜值" << endl;
	mm.operator>>(cin);
	mm.operator<<(cout);
	return 0;
}

ostream& MM::operator<<(ostream& out)
{
	out << this->name << '\t' << this->faceScore << endl;
	return out;
}

istream& MM::operator>>(istream& in)
{
	in >> this->name >> this->faceScore;
	return in;
}

上面的代码是可以实现的,也可以正常的输入和输出。但是

mm.operator<<(cout);
mm.operator>>(cin);

是显式调用,而且必须是显式调用才不会报错。那这样看来就比较不舒服了。用户希望的是下面的样子

cout<<mm;
cin>>mm;

而实现这样的效果,那么流运算符的重载就必须使用友元函数的方式进行重载

直接看代码

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

class MM
{
public:
	//使用缺省的方式写构造函数
	MM(string name="Alice",int faceScore=100):name(name),faceScore(faceScore){}
	friend ostream& operator<<(ostream& out, MM& mm);		//友元重载输出<<
	friend istream& operator>>(istream& in, MM& mm);		//友元重载输入>>
protected:
	string name;
	int faceScore;
};

int main()
{
	MM mm;
	cout << mm << endl;		//可以隐式调用
	cout << "请输入mm的信息:" << endl;
	cin >> mm;
	cout << mm << endl;
	operator<<(cout, mm);	//也可以显示调用
	return 0;
}

ostream& operator<<(ostream& out, MM& mm)
{
	out << mm.name << '\t' << mm.faceScore << endl;
	return out;
}

istream& operator>>(istream& in, MM& mm)
{
	in >> mm.name >> mm.faceScore;
	return in;
}

对运算符流重载的小结:

  • 可以使用类的成员函数重载
  • 也可以使用友元函数重载
  • 为了更简洁的隐式调用,亲近人的思维,一般使用友元函数重载

运算符重载之隐式转换

隐式转换在基本数据类型中是很常见的,就是使用不同的数据类型来相互赋值,然后还不报错。隐式转换就起到这样的作用。

在基本数据类型中,浮点型的变量赋值给整型变量,小数部分会被截断,只留下整数部分。

double dNum=3.1415926;
int iNum=dNum;	//iNum=3

那么我们想使用自定义类型的对象赋值给基本数据类型的对象的时候,也想让它可以隐式转换的话就必须使用运算符重载。

基本语法:

operator 要转换的类型(){ return 对应的类型; }

operator前面不写返回值类型,后面的int是要转换的类型,()里面填参数,不能省略括号

直接看代码

#include<iostream>
using namespace std;

class MM
{
public:
	//使用了缺省的方式写构造函数
	MM(string name="Alice",int age=0):name(name),age(age){}
	//重载int类型的隐式转换
	operator int()	//operator前面不写返回值类型,后面的int是要转换的类型,()里面填参数,不能省略括号
	{
		return this->age;
	}
protected:
	string name;
	int age;
};

int main()
{
	MM mm("小可爱", 18);
	//没有写重载之前是错的	//E0413	不存在从 "MM" 到 "int" 的适当转换函数
	int i = mm;
	cout << i << endl;

	return 0;
}

要重载其他类型的也可以,使用隐式转换的重载,并且要注明是哪个类型的就行,上面的代码是以重载int隐式转换的例子。

默认的 ‘=’ 重载运算符

在C++类中,如果没有写 ‘=’ 的运算符重载函数是会存在一个默认的重载函数,使得程序在执行类的对象赋值给类的对象语句的时候不会报错。

C++类中的默认存在的函数

  • 默认的构造函数
  • 默认的拷贝构造函数,浅拷贝
  • 默认的 ‘=’ 重载函数

这些函数,如果自己没有写,是会在类中默认存在,如果写了,默认的就不存在了。

//没写 '='重载函数时
#include<iostream>
using namespace std;

class A
{
public:
    //有参构造函数,写了之后默认的构造函数就不存在了
    //A(){}这个是默认的构造函数长的样子
    A(int i,double d):i(i),d(d){}
    A(A& obj):i(obj.i),d(obj.d)
    {
        cout<<"拷贝构造函数"<<endl;
    }
protected:
    int i;
    double d;
};

int main()
{
    A a(2,3.1);
    A b(4,5.2);
    a=b;	//这个是成立的,因为存在一个默认的'='重载函数,调用的是赋值重载函数
    A c=a;	//这个也是成立的,但是这个不的调用赋值重载,而是调用拷贝构造函数
    return 0;
}
/*
	输出结果:
	拷贝构造函数
*/

把下面的代码下到上面的类的public中去

    void operator=(A& obj)
    {
        i = obj.i;
        d = obj.d;
        cout << "赋值重载函数" << endl;
    }

然后输出结果就是:

赋值重载函数
拷贝构造函数

如果赋值重载函数的参数传的不是引用类型,那在程序运行的时候还会调用一下拷贝构造函数,因为void operator=的参数列表中的A obj是进行下面操作

A obj=传进来的对象;	这个时候就是调用的拷贝构造
然后下面才开始执行operator=函数里面的内容

注意的细节就是:

//假设A是一个类
A a;
A b=a;	//这个是调用拷贝构造
A c;
c=a;	//这个是调用赋值重载

重载加常量

在之前的重载 '+'等运算符的时候,都是可以实现对象加一个常量的,但是它们并不存在交换律(也就是对象加常量可以,但是常量加对象就不行)。那怎么解决这个问题呢。就直接使用友元重载就可以了。

#include<iostream>
using namespace std;

class MM
{
public:
	MM(string name="",int age=0):name(name),age(age){}
	MM operator+(int num)
	{
		return MM(this->name,this->age + num);
	}
	void print()
	{
		cout << this->name << '\t' << this->age << endl;
	}
	friend MM operator+(int num,MM mm);
protected:
	string name;
	int age;
};

int main()
{
	MM mm("Alice", 4);
	MM mm2 = mm + 6;
    //显式调用解析过程:mm.operator+(6)
	mm2.print();
	MM mm3 = 5 + mm2;	//没写友元重载函数之前是错的
    //显式调用解析过程:operator+(5,mm2)
	return 0;
}

MM operator+(int num, MM mm)
{
	return MM(mm.name,mm.age+num);
}

  • 重载加常量的内容还有一个不正常的写法,但是并没什么用,了解即可。直接看代码就知道了。
#include<iostream>
using namespace std;

class MM
{
public:
	MM(int age = 3):age(age){}
	friend MM operator+(MM mm1, MM mm2);
protected:
	int age;	//只有一个属性
};

int main()
{
	MM mm1(4);
	MM mm2;
	//下面的代码没有问题
    //因为存在一个强制转换的过程,
	mm2 = 5 + mm1;
	MM mm3 = mm2 + 9;
	return 0;
}

MM operator+(MM mm1, MM mm2)
{
	return MM(mm1.age+mm2.age);
}

看到上面的代码能这样搞是没问题的,但前提是这个类里面只有一个属性(而且是基本数据类型)这样才能够使用强转。然后就能使用对象加常量和常量加对象的操作了。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-08-19 11:52:27  更:2021-08-19 11:53:07 
 
开发: 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/27 5:07:35-

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