C++中的链式操作
2015-07-18 16:52
295 查看
代码编译环境:Windows7 32bits+VS2012。
链式操一定涉及到结合律的问题,例如链式操作赋值操作满足右结合律,即a=b=c被解释成a=(b=c),而链式输出操作原则满足左结合律,即
(1)操作符重载函数一定不能返回void类型。
因为void类型不能参与任何运算,所以,操作符重载函数返回void类型实际上是阻止了链式操作的可能性。
(2)对赋值操作符进行重载,如果返回的是类的对象,那么链式赋值操作必须借助于拷贝构造函数才能进行。这样不懂那会有较大的运行开销,还要编写正确的拷贝构造函数。考察下面的程序。
程序的运行结果是:
可以看到,在连续的两次赋值操作过程中,一共两次调用拷贝构造函数。第一次发生在执行c2=c1的操作中,函数的返回值(临时对象)是由c1构造的,这时发生了一次拷贝构造函数的调用;第二次发生在为c3赋值的时候,赋值运算的返回值仍然是一个Complex类的对象,这时又发生了一次拷贝构造函数的调用。让赋值操作依赖于拷贝构造函数,显然不是一种明智的做法。
思考:
仅仅将赋值运算符重载函数的申明和定义修改如下:
同样是上面的程序,输出结果为:
也就是说,一次拷贝构造函数都没有调用,原因是赋值操作符函数返回Complex类的引用,不用产生一个新的临时对象,这样大大提高了程序运行效率。所以,赋值运算符重载几乎无一例外地返回引用。
一般来说,实现输入操作符重载,一律采用如下函数原型:
而实现输出操作符重载,一律采用如下函数原型:
如果操作符函数的返回的是istream或ostream类的对象,而不是引用,会出现编译错误。出错的原因以及关于输入输入操作符的重载,敬请期待我的后续blog。
1.什么是链式操作
链式操作是利用运算符进行的连续运算(操作),它的特点是在一条语句中出现两个或者两个以上相同的操作符,如连续的赋值操作、连续的输入操作、连续的输出操作、连续的相加操作等都是链式操作的例子。链式操一定涉及到结合律的问题,例如链式操作赋值操作满足右结合律,即a=b=c被解释成a=(b=c),而链式输出操作原则满足左结合律,即
cout<<a<<b被解释成
(cout<<a)<<b,基本数据类型的链式操作都有明确的定义,而涉及到类类型的链式操作则往往需要进行相应操作符的重载。
2.类的链式操作
为了实现类的链式操作,使链式操作能够进行,操作符的重载必须满足一定的要求:(1)操作符重载函数一定不能返回void类型。
因为void类型不能参与任何运算,所以,操作符重载函数返回void类型实际上是阻止了链式操作的可能性。
(2)对赋值操作符进行重载,如果返回的是类的对象,那么链式赋值操作必须借助于拷贝构造函数才能进行。这样不懂那会有较大的运行开销,还要编写正确的拷贝构造函数。考察下面的程序。
#include <iostream> using namespace std; class Complex{ double real; double image; public: Complex(double r=0.0,double i=0.0){ real=r; image=i; } Complex(const Complex& c){ cout<<"Copy Constructor"<<endl; real=c.real; image=c.image; } void Show(){ cout<<real<<"+"<<image<<"i"<<endl; } Complex operator=(const Complex&); }; Complex Complex::operator=(const Complex& c) { real=c.real; image=c.image; return *this; } int main(int argc,char* argv[]) { Complex c1(2.3,4.5),c2,c3; c1.Show(); c3=c2=c1; c2.Show(); c3.Show(); getchar(); }
程序的运行结果是:
可以看到,在连续的两次赋值操作过程中,一共两次调用拷贝构造函数。第一次发生在执行c2=c1的操作中,函数的返回值(临时对象)是由c1构造的,这时发生了一次拷贝构造函数的调用;第二次发生在为c3赋值的时候,赋值运算的返回值仍然是一个Complex类的对象,这时又发生了一次拷贝构造函数的调用。让赋值操作依赖于拷贝构造函数,显然不是一种明智的做法。
思考:
Complex& Complex::operator=(Complex& c){…},会有什么结果?
仅仅将赋值运算符重载函数的申明和定义修改如下:
Complex& operator=(const Complex&); Complex& Complex::operator=(const Complex& c) { real=c.real; image=c.image; return *this; }
同样是上面的程序,输出结果为:
也就是说,一次拷贝构造函数都没有调用,原因是赋值操作符函数返回Complex类的引用,不用产生一个新的临时对象,这样大大提高了程序运行效率。所以,赋值运算符重载几乎无一例外地返回引用。
3.实现输入输出的链式操作
输入操作符(>>)和输出操作符(>>)的重载函数必须返回引用,否则链式无法操作无法完成。一般来说,实现输入操作符重载,一律采用如下函数原型:
istream& operator>>(istream&, className&);
而实现输出操作符重载,一律采用如下函数原型:
ostream& operator<<(ostream&, className&);
如果操作符函数的返回的是istream或ostream类的对象,而不是引用,会出现编译错误。出错的原因以及关于输入输入操作符的重载,敬请期待我的后续blog。
参考文献
[1] ]陈刚.C++高级进阶教程[M].武汉:武汉大学出版社,2008.相关文章推荐
- C++中的链式操作
- 一起talk C栗子吧(第二十回:C语言实例--括号匹配)
- java的接口和C++虚类的相同和不同之处
- freopen - C/C++文件输入输出利器
- C语言中的格式字符 格式修饰符 运算符的优先级
- 2015年ALPC暑期专题练习I (计算几何) A
- 算法导论 第二十一章:不相交集合森林
- C++实现简单的对象池
- C语言程序设计9
- 作死向之C++告别演出——课程设计(银行储蓄系统(大BUG+功能不完整版))
- C语言程序设计7--8章
- C++ 使用STL string 实现的split,trim,replace-修订
- C++ 使用STL string 实现的split,trim,replace-修订
- C++ string.replace的使用
- C++ string.replace的使用
- C++ typedef用法小结
- iOS C语言7.2_结构体多文件
- 【C++】指针解析
- C++智能指针
- VC++ 控件赋值取值