操作符重载之输出操作符(C++)

操作符重载 之 输出操作符"<<"(C++)

  • 问题背景
  • 技术推演
  • 解决方案
  • 总结

阅读之前注意:

本文阅读建议用时:30min
本文阅读结构如下表:

项目 下属项目 测试用例数量
问题背景 0
技术推演 2
解决方案 2
总结 0

问题背景

在C++中,我们自己定义了一个类,但我们却不能用cout来直接输出这个自定义类的具体对象。你可以试一试,编译器会报错的,这主要是因为编译器不知道该按照什么方式来输出你自定义的类。
那我们就想用cout来直接输出呢?怎么办呢?哈哈,我们有利器——操作符重载!这样我们就可以规定输出方式,有了规则,编译器看到我们的这个类的对象就知道怎么输出了。

技术推演1

首先我们要承认的是,C++是把操作符重载用函数来实现的2

比如我们要实现下面的自定义类A的对象的加法,该怎么做呢?自然能够想到的,就是用函数来把对象中的每个成员变量做加法,参考以下代码:

#include"iostream"
using namespace std;

class A{
public:
	A(int a = 0, int b = 0)//使用默认参数,这样既是有参构造函数,也是默认构造函数
	{
		this->a = a;
		this->b = b;
	}
public://为了方便起见,设置为public
	int a;
	int b;
};

A addA(A &A1,A &A2)//实现对象加法的函数
{
	A tmp;
	tmp.a = A1.a + A2.a;
	tmp.b = A1.b + A2.b;
	return tmp;
}

void main()
{
	A a1(1, 2), a2(3, 4);
	A a3 = addA(a1, a2);//用函数来做对象的加法
	cout << "a" << a3.a << " b" << a3.b << endl;
	system("pause");
}

接下来我们看看操作符重载是怎么用函数实现的:

#include"iostream"
using namespace std;

class A{
public:
	A(int a = 0, int b = 0)//使用默认参数,这样既是有参构造函数,也是默认构造函数
	{
		this->a = a;
		this->b = b;
	}
public://为了方便起见,设置为public
	int a;
	int b;
};

A operator+(A &A1,A &A2)//操作符重载
{
	A tmp;//这里会调用默认构造函数
	tmp.a = A1.a + A2.a;
	tmp.b = A1.b + A2.b;
	return tmp;
}

void main()
{
	A a1(1, 2), a2(3, 4);
	A a4 = operator+(a1, a2);
	A a5 = a1 + a2;
	cout << "a" << a4.a << " b" << a4.b << endl;
	cout << "a" << a5.a << " b" << a5.b << endl;
	system("pause");
}

上面代码中是用全局函数来实现操作符重载,事实上这并不是正规写法,但为了方便理解,正不正规姑且不论。在main函数中,我们可以看到语句“A a4 = operator+(a1, a2);”和语句“A a5 = a1 + a2;”的效果都是一样的。
因此我们可以推测,C++编译器在看到自定义类型在做加法时,也就是看到+号,它会自动的调用重载函数,把左操作对象(+号左边的对象)和右操作对象(+号右边的对象)分别传入重载函数。这样一来,我们就知道C++确实是把操作符重载用函数来实现的。

解决方案

思路:根据以上的技术推演,我们可以同样的应用在“<<”操作符上,那么这个操作符重载的话,需要什么参数呢?毫无疑问,我们自定义类型的对象的参数需要传进去。
我们先看看以下代码:

#include"iostream"
using namespace std;

void main()
{
	int a = 10;
	char *b = "hello, world";
	cout << a;
	cout << b;
	system("pause");
}

可以看到,基础的类型(也就是int和字符串指针类型)作为了参数,但还有一个参数,看来看去,就只有cout了=-=,哈哈,想不到吧,cout竟然也是一个参数。
其实如果我们右键查看一下cout,就能看到下面图片中的内容
cout
看到了吧,cout前面带着一个类型说明符“ostream”,即cout也是一个类的对象。
这样我们就知道重载"<<"需要哪些参数了:一个是ostream类型的对象,还有一个就是我们自定义类型A的对象。
下面我们就来实现它!
参考以下代码:

#include"iostream"
using namespace std;

class A{
public:
	A(int a = 0, int b = 0)//使用默认参数,这样既是有参构造函数,也是默认构造函数
	{
		this->a = a;
		this->b = b;
	}
public://为了方便起见,设置为public
	int a;
	int b;
};

void operator<<(ostream &out,A &a1)//操作符重载
{
	out << "a" << a1.a << " b" << a1.b << endl;//这里直接用out
}

void main()
{
	A a1(1, 2), a2(3, 4);
	cout<<a1;
	cout<<a2;
	system("pause");
}

总结

事实上以上代码均不是正规写法,正规写法链接将在以后给出。
最后引用王保明先生的一句话来给本文做总结:“结论倍简单的:首先我们要承认一件事,C++中操作符的重载是用函数来实现的”。

如果本文对你有帮助,不如请我一罐可乐吧 🍼

在这里插入图片描述


  1. 基于王保明先生的技术推演,王老师讲课真的很不错! ↩︎

  2. 结论基于王保明先生的讲课内容. ↩︎

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章