C++-Record31—友元函数实现左移右移操作符重载

目录

友元函数实现左移右移操作符重载的过程

左右移运算符要支持链式编程

友元函数重载操作符使用注意点

总体代码


友元函数实现左移右移操作符重载的过程

这里要先强调一下,关于工程实际的应用场景中,运算符重载一般都是使用成员函数来完成的,使用友元函数声明的全局函数的情况是非常少的!但是,但是,但是,在某些场景下,只能使用友元函数来进行实现。

下面提供一个运算符重载的正规案例,通过友元函数来重载左移右移操作符,这个操作只能由友元声明的全局函数来实现,因为用成员函数的话,要重载左移右移操作符,就先找到对应的"cout"对象的,这个类在ostream类中(拿不到源码)中存在,而这个库的内容是不能被轻易修改的。所以,只能用全局函数的方法来实现,这也才是友元函数实现重载的最最真实、独有的场景!

ostream& operator<<(ostream &out, Complex &c1)
{
	out<<"12345 生活真是苦"<<endl;
	out<<c1.a << " + " << c1.b << "i" << endl;
	return out;
}

void main()
{
	int a = 10;
	Complex c1(1, 2), c2(3, 4);
	cout<<a<<endl; //按照数据类型 

	//1
	cout << c1 ;
	//2 ostream 类中 添加 成员函数 .operator<<
	//ostream
	//cout.operator<<(c1);

	//2 函数返回值当左值 需要返回一个引用
	cout << c1  << "aaddddd";
	//
	//cout.operator<<(c1) .operator<<("aaddddd");
	//void.operator<<("aaddddd");

	system("pause");
}

其中,Complex类是上篇博客所定义的类,此处仅作展示,详情见总体代码部分。这个就是通过友元声明的全局函数来进行定义的,声明部分如下:

class Complex
{
private:
	int a;
	int b;
	//friend void operator<<(ostream &out, Complex &c1);
	friend ostream& operator<<(ostream &out, Complex &c1);

}

左右移运算符要支持链式编程

再多说一点左右移运算符调用是讲顺序的,要支持链式编程:

在执行以下代码中:

	cout << c1  << "aaddddd";

完整的代码执行逻辑实际为:

	cout.operator<<(c1) .operator<<("aaddddd");

 先调用"cout.operator<<(c1) .operator",再调用"(c1) .operator<<("aaddddd")",实际是执行了两次运算符操作。而如果将原来的左右移运算符重载的函数类型定义成:

void operator<<(ostream &out, Complex &c1)

那么,在执行第一个左右移运算符返回值为void类型,作为下一次左右移运算符的输入,就会报错。所以,在定义左右移运算符的时候返回类型应该为统一的"ostream&"类型。

友元函数重载操作符使用注意点

1. 友员函数重载运算符常用于运算符的左右操作数类型不同的情况

2. 其他

  • 在第一个参数需要隐式转换的情形下,使用友员函数重载运算符是正确的选择

  •  友员函数没有 this 指针,所需操作数都必须在参数表显式声明,很容易实现类型的隐式转换

  •  C++中不能用友员函数重载的运算符有:

        =    ()    []    ->

总体代码

dm03_运算符重载正规的写法.cpp


#include <iostream>
using namespace std;

/*
class ostream
{

};
*/

class Complex
{
private:
	int a;
	int b;
	//friend void operator<<(ostream &out, Complex &c1);
	friend ostream& operator<<(ostream &out, Complex &c1);

public:
	Complex(int a=0, int b=0)
	{
		this->a = a;
		this->b = b;
	}
	void printCom()
	{
		cout<<a<<" + " << b << "i" <<endl;
	}
public:

	//实现 + 运算符重载
	Complex operator+(Complex &c2)
	{
		Complex tmp(a + c2.a, b + c2.b);
		return tmp;
	}

	//前置++
	Complex& operator++()
	{
		a++;
		b++;
		return *this;
	}

	//后置++
	Complex operator++(int)
	{
		//先使用 在让c1加加
		Complex tmp = *this;
		//return c1;
		this->a ++;
		this->b ++;
		return tmp;
	}
	//成员函数法 实现 -运算符重载
	 Complex operator-(Complex &c2)
	{
		Complex tmp(this->a - c2.a, this->b - c2.b);
		return tmp;
	}

	 //前置--
	Complex& operator--()
	{
		this->a --;
		this->b --;
		return *this;
	}

	//后置--
	Complex operator--(int)
	{
		Complex tmp = *this;
		this->a--;
		this->b--;
		return tmp;
	}
};


void main31()
{
	Complex c1(1, 2), c2(3, 4);

	//1	全局函数法 实现 + 运算符重载
	// Complex operator+(Complex &c1, Complex &c2);
	Complex c3 = c1 + c2;
	c3.printCom();

	//2 成员函数 法 实现 -运算符重载
	//c1.operator-(c2);
	//Complex operator-(Complex &c2)
	Complex c4 = c1 - c2;
	c4.printCom();

	//前置++操作符 用全局函数实现
	++c1;
	c1.printCom();

	//前置--操作符 成员函数方法
	--c1;
	c1.printCom();
	//Complex& operator++(Complex &c1)
	//c1.operator--();

	//后置++操作符 用全局函数实现
	c1++;
	c1.printCom();

	//后置--操作符 用成员函数实现
	c1--;
	c1.printCom();
	//c1.operator--()
	
	cout<<"hello..."<<endl;
	system("pause");
	return ;
}

/*
void operator<<(ostream &out, Complex &c1)
{
	out<<"12345 生活真是苦"<<endl;
	out<<c1.a << " + " << c1.b << "i" << endl;
}
*/

ostream& operator<<(ostream &out, Complex &c1)
{
	out<<"12345 生活真是苦"<<endl;
	out<<c1.a << " + " << c1.b << "i" << endl;
	return out;
}

void main()
{
	int a = 10;
	Complex c1(1, 2), c2(3, 4);
	cout<<a<<endl; //按照数据类型 

	//1
	cout << c1 ;
	//2 ostream 类中 添加 成员函数 .operator<<
	//ostream
	//cout.operator<<(c1);

	//2 函数返回值当左值 需要返回一个引用
	cout << c1  << "aaddddd";
	//
	//cout.operator<<(c1) .operator<<("aaddddd");
	//void.operator<<("aaddddd");

	system("pause");
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值