【C++总复习】 第4章----运算符重载

说在前面:C++将C语言中的左移运算符(<<)进行了运算符重载,变成了与流对象cout配合使用的流插入运算符;将右移运算符(>>)进行了运算符重载,变成了与流对象cin配合使用的流提取运算符,这就是利用了运算符重载。

运算符重载格式:
函数类型 operator 运算符名称(形参表)
{ 对运算符重载处理 }

例如:
A operator + (A &);
重载了类A的“+”运算符
“operator +“重载了运算符”+”

1.双目运算符重载

1.1 operator +

功能:用"+"实现两个复数对象的相加

1.重载为类的成员函数

#include <iostream>
using namespace std;

class Complex
{
private:
	double real;	//定义实部
	double imag;	//定义虚部
public:
	//构造函数
	Complex(){
		real = 0.0;
		imag = 0.0;
	}
	Complex(double r, double i){
		real = r;
		imag = i;
	}

	//输出实部虚部
	void display(){ 
		cout << "(" << real << ", " << imag << "i)" << endl; 
	}

	//重载运算符 +
	Complex  operator +(Complex &c2){ //加号实现了两个对象的以下功能
		Complex c;
		c.real = this->real + c2.real;
		c.imag = this->imag + c2.imag;
		return c;
	}
};

int main(){
	Complex c1(3, 4), c2(4, 5), c3; 
	//定义3个复数对象,c3用于存放c1对象与c2对象的和

	c3 = c1 + c2;	//利用重载的+进行对象运算

	cout << "c1 = "; 
	c1.display();

	cout << "c2 = "; 
	c2.display();

	cout << "c1 + c2 = ";
	c3.display();
	
	system("pause");
	return 0;
}

2.重载为类的友元函数

#include <iostream>
using namespace std;

class Complex
{
private:
	double real;	//定义实部
	double imag;	//定义虚部
public:
	//构造函数
	Complex(){
		real = 0.0;
		imag = 0.0;
	}
	Complex(double r, double i){
		real = r;
		imag = i;
	}

	//输出实部虚部
	void display(){ 
		cout << "(" << real << ", " << imag << "i)" << endl; 
	}

	//重载运算符 +
	friend Complex operator+(Complex &c1 ,Complex &c2);
};
Complex operator +(Complex &c1, Complex &c2)
{
	Complex c;
  	c.real=c1.real+c2.real;
  	c.imag=c1.imag+c2.imag;
  	return c;
}

int main(){
	Complex c1(3, 4), c2(4, 5), c3; 
	//定义3个复数对象,c3用于存放c1对象与c2对象的和

	c3 = c1 + c2;	//利用重载的+进行对象运算

	cout << "c1 = "; 
	c1.display();

	cout << "c2 = "; 
	c2.display();

	cout << "c1 + c2 = ";
	c3.display();
	
	system("pause");
	return 0;
}
  • 重载为友元函数与成员函数的主要区别在于其参数个数不同
  • 成员函数通过this指针传递给运算符左边的操作数,而友元函数则没有this指针,必须显式传递所有参数。
  • 对+进行运算符重载之后,可以实现两个对象内部相应数据的运算,扩大了+号可运算数据的集合,同时也方便了很多

警告:上述代码不能实现c3 = 3 + c2,原因是与形参类型不匹配,重载之后的+号只能实现对象之间的相加

1.2 operator >

功能:比较两个字符串的大小

#include <iostream>
using namespace std;

class String
{
private:
	char *p;
public:
	//构造函数
	String(){ 
		p = NULL; 
	}
	String(char *str){
		p = str;
	}

	//输出字符串
	void display(){
		cout << p;
	}

	//重载 > 运算符为友元函数
	friend bool operator>(String &string1, String &string2);
};

bool operator>(String &string1, String &string2)
{
	if (strcmp(string1.p, string2.p)>0)
		return true;
	else
		return false;
}
int main()
{
	String string1("Hello"), string2("Book");

	cout << (string1>string2) << endl;

	system("pause");
	return 0;
}

2.单目运算符重载

2.1 operator ++(前置)

  • 格式:函数类型 operator ++( );

有一个Time类,包含数据成员minute和sec,模拟秒表,每次走一秒,满60秒进一分钟,此时秒又从0开始算。要求输出分和秒的值。

#include <iostream>
using namespace std;

class Time
{
private:
	int minute;
	int sec;

public:
	//构造函数
	Time() { minute = 0; sec = 0; }
	Time(int m, int s):minute(m), sec(s) {}

	//输出时间
	void display() { cout << minute << ":" << sec << endl; }

	//重载前置++运算符
	Time operator++();
};
Time Time::operator++(){
	sec++;
	if (sec >= 60)
	{
		sec -= 60;
		++minute;
	}
	return *this;
}

int main(){

	Time time1(34, 0);

	for (int i = 0; i<61; i++)	//模拟时间过去了61秒
	{
		++time1;
		time1.display();
	}

	system("pause");
	return 0;
}

2.2 operator ++(后置)

  • 格式:函数类型 operator ++(int);
#include <iostream>
using namespace std;

class Time
{
private:
	int minute;
	int sec;

public:
	//构造函数
	Time() { minute = 0; sec = 0; }
	Time(int m, int s):minute(m), sec(s) {}

	//输出时间
	void display() { cout << minute << ":" << sec << endl; }

	//重载前置++运算符
	Time operator++();

	//重载后置++运算符
	Time operator++(int);
};

Time Time::operator++(){
	sec++;
	if (sec >= 60)
	{
		sec -= 60;
		++minute;
	}
	return *this;
}

Time Time::operator++(int)
{
	Time temp(*this);
	sec++;
	if (sec >= 60)
	{
		sec -= 60;
		++minute;
	}
	return temp;
}

int main(){

	Time time1(34, 59), time2;

	cout << " time1 : ";
	time1.display();

	++time1;
	cout << "++time1: ";
	time1.display();

	time2 = time1++;	//time2为自增前的值
	cout << "\ntime2 = time1++;\ntime1 : ";
	time1.display();

	cout << "time2 : ";
	time2.display();

	system("pause");
	return 0;
}

3.重载流插入运算符和流提取运算符

Q:为什么流插入运算符和流提取运算符只能使用友元函数,却不可以使用成员函数呢?
A:因为调用该重载运算符的对象分别是istream类和ostream类对象,并不是用户自定义的类对象,所以无法把<<和>>重载为用户自定义类的成员函数。

3.1 operator <<

功能:利用<<输出对象信息

#include <iostream>
using namespace std;
class Complex
{
private:
	double real;
	double imag;

public:
	//构造函数
	Complex(){ 
		real = 0; 
		imag = 0; 
	}
	Complex(double r, double i){ 
		real = r; 
		imag = i; 
	}

	//对+运算符重载
	Complex operator + (Complex &c2);

	//对<<运算符重载
	friend ostream& operator <<(ostream&, Complex&);
};

Complex Complex::operator + (Complex &c2)
{
	return Complex(real + c2.real, imag + c2.imag);
}

ostream& operator << (ostream& output, Complex& c)
{
	output << "(" << c.real << "+" << c.imag << "i)" << endl;
	return  output;
}

int  main()
{
	Complex c1(2, 4), c2(6, 10), c3;

	c3 = c1 + c2;	//用重载的+进行对象运算

	cout << c3 << c1;	//用重载的cout进行对象输出

	system("pause");
	return 0;
}

Q:为什么ostream& operator << (ostream& output, Complex& c)的返回值是ostream对象的引用?
A:因为cout << c3 << c1是一个对象一个对象输出的,先输出c3对象,然后返回一个cout,再进行cout<<c1;

3.2 operator >>

功能:利用>>输入对象信息

#include <iostream>
using namespace std;

class Complex
{
private:
	double real;
	double imag;
public:	
	//重载<<运算符用来输出对象信息
	friend ostream& operator << (ostream&, Complex&);
	//重载>>运算符用来读取对象信息
	friend istream& operator >> (istream&, Complex&);
};

ostream& operator << (ostream& output, Complex& c)
{
	output << "(" << c.real << "+" << c.imag << "i)";
	return output;
}
istream& operator >> (istream& input, Complex& c)
{
	cout << "input real part and imaginary part of complex number:";
	input >> c.real >> c.imag;
	return input;
}
int main()
{
	Complex c1, c2;
	cin >> c1 >> c2;
	cout << "c1=" << c1 << endl;
	cout << "c2=" << c2 << endl;
	return 0;
}

4.重载运算符总结

  • 1.不允许用户自定义新的运算符,只能对已有的C++运算符进行重载
  • 2.C++中不允许重载的运算符有5个:成员访问运算符( . )、成员指针访问运算符( * )、域运算符( :: )、长度运算符( sizeof )、条件运算符( ?: )
  • 3.C++中允许重载的运算符有(见图)
    在这里插入图片描述
  • 4.重载运算符不可以改变运算对象的个数
  • 5.重载运算符不能改变运算符的优先级别
  • 6.重载运算符不能改变运算符的结合性
  • 7.重载运算符的函数不能有默认参数(会与4相矛盾)
  • 8.重载运算符的操作对象中必须有一个是用户自定义的类对象
  • 9.理论上可以将运算符重载为执行任意操作的符号,但是由于可读性较差,不容易理解,所以应当使运算符重载之后的功能还之前的功能类似
  • 10.运算符重载扩展了原运算符可计算的数据类型的边界

5.不同类型数据间的转换

5.1 普通数据类型之间的转换

隐式类型转换

int i = 10;
i = 3.14 + i;
  • 在进行i = 3.14 + i;时,编译系统会把3.14看成double型数据处理,然后将+号右侧的 i 转换成double型,再与3.14相加,得到和13.14,再向整形变量i赋值,将13.5舍去小数位变成13,然后赋值给i。
  • 这一转换过程由编译器自动完成,用户不需干预,这种转换称为隐式转换

显式类型转换

int i = 10;
double d = (double) i;
  • 将整型 i 强制转换成double型的10.0再赋值给double型的d
  • 强制转换可能会导致数据的精度缺失

5.2 转换构造函数

  • 转换构造函数只有一个形式参数,这个参数可以是基本数据类型,也可以是一个某一个类的引用对象

1.参数为基本数据类型

Complex(double r){
	real = r;
	imag = 0.0;
}
  • 将一个基本数据类型转化为某类一个对象

2.参数为某类对象的引用

Teacher(Student &s){
	this->num = s.num;
	this->sex = s.sex;
	strcpy(this->name,s.name);
}
  • 将一个A类对象转化为另一个B类对象

5.3 类型转换函数

  • 类型转换函数就是在类中定义一个成员函数,其作用是将某类对象转换为某种基本数据类型
  • 函数格式:类名 :: operator 基本数据类型名(){ 具体转换语句 }
  • 例如:A :: operator float ( ){ return x+y; }

功能:将Complex对象转化为其实部double型数据返回

#include <iostream>
using namespace std;

class Complex
{
private:
	double real;
	double imag;
public:     
	//构造函数
	Complex(){ 
		real = 0; 
		imag = 0; 
	}
	Complex(double r, double i){
		real = r; imag = i;
	}
	//类型转换函数;将Complex对象转化为double型数据,
	//输出的是该对象的实部数据
	operator double()
	{
		return real;
	}
};
int main()
{
	Complex c1(3, 4), c2(5, -10), c3;

	double d;
	d = 2.5 + c1;

	cout << d << endl;
	return 0;
}

5.4 类型转换总结

在这里插入图片描述点击该链接,查看我的其他关于数据存储的博客:数据如何存储

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值