操作符重载 之 输出操作符"<<"(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前面带着一个类型说明符“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++中操作符的重载是用函数来实现的”。
如果本文对你有帮助,不如请我一罐可乐吧 🍼