1.operator<< && operator>>
在c++中,我们经常用到cin和cout进行输入输出,那么我们怎么使用cin和cout输入输出自定义类型呢
比如一个这样的日期类Date
class Date
{
private:
int _year;
int _month;
int _day
};
假如有日期类对象d1,d2,我们如何对他们进行输入输出呢?
下面这段代码,我详细演示了几种错误的实现方法和错误分析,以及正确的代码实现,请仔细看
Date.h
#pragma once
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
class Date
{
//friend void operator<<(std::ostream& out, Date& d);
friend std::ostream& operator<<(std::ostream& out, Date& d);
friend std::istream& operator>>(std::istream& in, Date& d);
public:
Date(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
//加入有一个日期类对象d,我们该如何实现cout<< d呢?
错误示例1
//void operator<<(std::ostream& out)
//{
// out << _year << "-" << _month << "-" << _day << endl;
//}
错误原因,在类内定义这个函数,实际调用的时候会转换成 d.operator<<(cout),
其中第一个参数是隐含的this指针,我们 cout << d,参数的位置传反了
虽然我们 d << cout 这样写可以正常跑,但是嘛跑的不太好看,这种方式pass
private:
int _year;
int _month;
int _day;
};
错误示例2
既然定义在类内会把参数传反,那干脆在类外面定义好了
//void operator<<(std::ostream& out, Date& d)
//{
// out << d._year << "-" << d._month << "-" << d._day << endl;
//}
错误原因 这样写参数位置是对上了,但是成员变量是私有的啊,类外面的函数不能访问呀。所以pass
错误示例3
类外面的函数通常是不能访问是不能访问类内的私有成员的,但是我可以定义成你的友元函数呀,这样就可以访问你的私有成员了
//void operator<<(std::ostream& out, Date& d)
//{
// out << d._year << "-" << d._month << "-" << d._day << endl;
//}
这样写会报一个链接错误,为什么呢?
我们现在把这个函数定义在头文件里面了,在预处理阶段,会把头文件在Date.cpp和Test.cpp都展开,这就导致了函数重定义,Pass
//错误示例4
//在错误3的基础上我们可以声明和定义分离,在Date.h里面定义该函数, 免得函数定义两次
//这样写似乎是没什么问题, 可是当我们 cout << d1 << d2的时候又报错了,因此我们还要在完善一下,
//正确做法
//在错误4的基础上,我们为了满足连续输出,我们只需要将cout作为函数返回值即可。
//接下来我们在顺手实现一些operator>>
Date.cpp
#include "Date.h"
错误示例4
//void operator<<(std::ostream& out, Date& d)
//{
// out << d._year << "-" << d._month << "-" << d._day << endl;
//}
std::ostream& operator<<(std::ostream& out, Date& d)
{
out << d._year << "-" << d._month << "-" << d._day << endl;
return out;
}
std::istream& operator>>(std::istream& in, Date& d)
{
in >> d._year >> d._month >> d._day;
return in;
}
2.总结
- 类外面的函数想访问类内的私有成员,定义友元函数。
- 头文件不要定义函数,会在所有包含了该.h的.cpp文件中展开造成函数重定义(类内的成员函数除外,因为成员函数默认是内联函数)
- this指针默认是类的成员函数的第一个参数
- 连续输入输出记得返回值