流插入运算符的重载
问题
问题1:cout << 5 << "this"; 为什么该语句可以成立?
问题2:cout是什么? “<<”为什么能用在cout上?
解答
cout是在iostream中定义的,ostream类的对象
“<<”能够用在cout上面,因为在iostream里对“<<”进行了重载
考虑
如何重载才能使得 cout << 5; 和 cout << "this"都成立?
方案
1 重载成ostream类的成员函数
void ostream::operator<<(int n)
{
.... // 输出n的代码
return;
}
2 cout << 5; 即 cout.operator<<(5);
cout << "this"; 即 cout.operator<<(“this”);
3 如何重载才能使得以下成立:
cout << 5 << "this";
分析:cout左移5的返回值还是cout,就可以继续往下运算
则运算符<<重载方式如下
ostream& ostream::operator<<(int n)
{
...... // 输出n的代码
return *this; // this指针指向成员函数所作用的对象,如果执行cout << 5,则this指针指向cout,*this就是cout,则函数返回值是cout的引用。
}
ostream& ostream::operator<<(const char* s)
{
.... // 输出s的代码
return *this;
}
则cout << 5 << "this";本质上的函数调用如下:
cout.operator<<(5).operator<<("this");
假定一下程序输出为5hello,该做些什么?(见本工程student.cpp)
//
// 流插入运算符的重载例子
//
#include <iostream>
using namespace std;
class CStudent{
public:
int nAge;
};
// 运算符 << 重载为全局函数 参数2取为CStudent的引用节省时间和空间,不需要生成形参对象,因为形参对象需要调用复制构造函数,有开销。
// 参数1 节省开销 也选择了ostream的引用 如果不选择ostream的引用,则编译出错。原因时形参与实参的差别
ostream& operator<<(ostream& o, const CStudent& s)
{
o << s.nAge;
return o; // 因为参数1 o是cout的引用 所以直接返回o即可。
}
int main()
{
CStudent s;
s.nAge = 5;
// 此处需要重载流插入运算符<< 由于ostream已经定义好的,因此只能重载为全局函数
cout << s << "hello";
return 0;
}
class CStudent{
public:
int nAge;
};
int main()
{
CStudent s;
s.nAge = 5;
cout << s << "hello";
return 0;
}
流提取运算符的重载
例题:
题目:假定c是Complex复数类的对象,现在希望写“cout << c;” 就能以“a + bi”的形式输出c的值,写“cin >> c;”就能从键盘接收“a + bi”形式的输入,并且使得c.real = a, c.imag = b;
答案:(见本项目complexcin.cpp)
//
// 题目:假定c是Complex复数类的对象,现在希望写“cout << c;” 就能以“a + bi”的形式输出c的值,写“cin >> c;”就能从键盘接收“a + bi”形式的输入,并且使得c.real = a, c.imag = b;
//
#include <iostream>
using namespace std;
class Complex{
private:
double real; double imag;
public:
Complex(double r = 0, double i = 0):real(r),imag(i){}
// 全局函数需要访问类Complex的私有成员,因此需要声明友元形式
friend ostream& operator<<(ostream& o, const Complex& c );
friend istream& operator >> (istream& i, Complex& c);
};
ostream& operator<<(ostream& o, const Complex& c ){
o << c.real << " + " << c.imag << "i ";
return o;
}
// 学习完string类之后回头来看。
istream& operator >> (istream& i, Complex& c){
string s;
i >> s; // 将“a + bi”作为字符串读入,“a+bi”中间不能有空格
int pos = s.find("+",0);
string sTmp = s.substr(0,pos); //分离处代表实部的字符串
c.real = atof(sTmp.c_str());
// atof库函数能够将const char*指针指向的内容转换
sTmp = s.substr(pos + 1, s.length()-pos-2);
// 分离处代表虚部的字符串
c.imag = atof(sTmp.c_str());
return i;
}
/**
* 程序运行结果可以是:
* 键盘输入 13.2 + 133i 87
* 13.2 + 133i 87
* */
int main()
{
Complex c;
int n;
// 需要重载 >> 运算符
cin >> c >> n;
// 需要重载 << 运算符 使用全局函数
cout << c << n;
return 0;
}