流插入运算符与流提取运算符重载,类型转换运算符的重载,自增、自减运算符的重载
流插入运算符的重载
cout是在iostream头文件中定义的,ostream类的对象。
“<<”可以用在cout上使用是因为在iostream中对“<<”进行了重载。
/*
如果下面程序输出为5hello,该如何补写
class CStudent
{
public:
int nAge;
};
int main()
{
CStudent s;
s.nAge = 5;
cout << s << "hello";
return 0;
}
*/
#include <iostream>
using namespace std;
class CStudent
{
public:
int nAge;
};
ostream &operator<<(ostream &o, const CStudent s)
{
o << s.nAge;
return o;
}
int main()
{
CStudent s;
s.nAge = 5;
cout << s << "hello";
return 0;
}
示例2
/*
例题:假设c是Complex复数类的对象,现在希望写“cout << c;”,就能以“a + bi”的形式输出c的值,
写“cin >> c;”,就可以从键盘接收“a + bi”形式的输入,并且使得c.real = a, c.imag = b;
*/
#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
class Complex
{
friend ostream &operator<<(ostream &os, const Complex &c);
friend istream &operator>>(istream &is, Complex &c);
private:
double real, imag;
public:
Complex(double r = 0, double i = 0):real(r), imag(i){}
};
ostream &operator<<(ostream &os, const Complex &c)
{
os << c.real << "+" << c.imag << "i"; //以a+bi的形式输出
return os;
}
istream &operator>>(istream &is, Complex &c)
{
string s;
is >> 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 *指针指向的内容转换成float
sTmp = s.substr(pos + 1, s.length() - pos - 2); //分离出代表虚部的字符串
c.imag = atof(sTmp.c_str());
return is;
}
int main()
{
Complex c;
int n;
cin >> c >> n;
cout << c << "," << n;
return 0;
}
/*
运行结果:
输入:
13.2+133i 87
输出:
13.2+133i,87
*/
类型转换运算符的重载
#include <iostream>
using namespace std;
class Complex
{
private:
double real, imag;
public:
Complex (double r = 0, double i = 0):real(r), imag(i){}
operator double() //不要写返回值类型
{
return real; //重载强制类型转换运算符double
}
};
int main()
{
Complex c(1.2, 3.4);
cout << (double)c << endl; //输出1.2。 (double)c 等价于 c.operator double()
double n = 2 + c; //自动转换c,等价于 double n = 2 + c.operator double()
cout << n; //输出3.2
return 0;
}
自增、自减运算符的重载
自增运算符++、自减运算符–有前置/后置之分,为了区分所重载的是前置运算符还是后置运算符,c++规定:
1、前置运算符作为一元运算符重载
重载为成员函数:
T &operator++();
T &operator–();
重载为全局函数:
T1 &operator++(T2);
T1 &operator–(T2);
2、后置运算符作为二元运算符重载,多写一个没用的参数
T &operator++(int);
T &operator–(int);
重载为全局函数:
T1 &operator++(T2, int);
T1 &operator–(T2, int);
注意:在没有后置运算符重载而有前置运算符重载的情况下,在vs中obj++也调用前置重载,而dev则令obj++编译出错。
#include <iostream>
using namespace std;
class CDemo
{
friend CDemo &operator--(CDemo &);
friend CDemo operator--(CDemo &, int);
private:
int n;
public:
CDemo(int i):n(i){}
CDemo &operator++(); //用于前置形式
CDemo operator++(int); //用于后置形式
operator int() //类型转换运算符的重载
{
return n;
}
};
CDemo &CDemo::operator++() //前置++
{
++n;
return *this;
} //++s即为:s.operator++();
CDemo CDemo::operator++(int k) //后置++
{
CDemo tmp(*this); //记录修改前的对象
n++;
return tmp; //返回修改前的对象
} //s++即为:s.operator++(0);
CDemo &operator--(CDemo &d) //前置--
{
--d.n;
return d;
} //--s即为:s.operator--(s);
CDemo operator--(CDemo &d, int k) //后置--
{
CDemo tmp(d);
d.n--;
return tmp;
} //s--即为:s.operator--(s, 0);
int main()
{
CDemo d(5);
cout << (d++) << ","; //等价于d.operator++(0);
cout << d << ",";
cout << (++d) << ","; //等价于d.operator++();
cout << d << endl;
cout << (d--) << ","; //等价于d.operator--(d, 0);
cout << d << ",";
cout << (--d) << ","; //等价于d.operator--(d);
cout << d << endl;
return 0;
}
//++a的返回值是a的引用, a++的返回值不是一个引用,而是一个临时对象
/*
输出:
5,6,7,7
7,6,5,5
*/
运算符重载的注意事项:
1、c++不允许定义新的运算符;
2、重载后运算符的含义应该符合日常习惯;
3、运算符重载不改变运算符的优先级;
4、“.”、“.*”、“::”、“?:”、sizeof这些运算符不能被重载;
5、重载运算符()、[]、->或者赋值运算符=时,运算符重载函数必须声明为类的成员函数。