【十一】运算符重载(下)
2015-08-23 09:54
302 查看
1、回顾上一节
上一节中,我们通过了两个全局友元函数进行了运算符重载,并且简单说明了如何进行类成员函数的运算符重载,这里首先将全局重载函数改写为成员重载函数!
示例:
思考:
什么时候使用全局函数重载操作符?什么时候使用成员函数重载操作符?
当无法修改左操作数的类的实现时,使用全局函数进行重载,用这种方法也能对原有的类进行功能扩展,即使我们没有源代码
C++规定,=, [], ()和->操作符只能通过成员函数进行重载
2、类的默认操作符重载
C++编译器会为每个类提供默认的赋值操作符,既是拷贝构造函数
默认的赋值操作符只是做简单的值复制
类中存在指针成员变量时就需要重载赋值操作符,因为一旦只进行简单的值复制,那么两个对象的的成员变量就同时指向了同一内存空间,这就会引发问题,比如,b对象是a对象的拷贝,如果a对象被析构,那么它申请的内存空间会被释放,而b对象此时正“使用”着该内存空间!
3、“++”和“–”运算符的重载
这两个操作符只有一个操作数
这两个操作符有前缀和有后缀的区分
思考:
那么,如何重载这两个操作符才能区分前置运算和后置运算??
答案:
可以通过占位参数来实现,因为操作符的重载本质上还是函数的重载,所以可以用参数的不同来区分两者,这里实现“++”运算符的重载来举例说明!
示例:
4、不应该被重载的运算符
最好不要去重载”&&”、”||” 和 “,” 运算符,原因如下:
&&和||内置实现了短路规则
“,”号运算符的重载版本无法保证它原有的求值顺序
操作符重载是靠函数重载来完成的
操作数作为函数参数传递
C++的函数参数都会被求值,无法实现短路规则
5、不能被重载的运算符
‘::’ – 作用域运算符
‘.*’ – 成员指针运算符
‘.’ – 成员运算符
‘? :’ – 条件运算符
‘sizeof’ – sizeof运算符
TIPS:
”.*/->*” – 成员指针运算符的使用举例
6、小结
操作符重载可以直接使用类的成员函数实现
=, [], ()和->操作符只能通过成员函数进行重载
++操作符通过一个int参数进行前置与后置的重载
C++中不要重载&&、|| 和 , 操作符
C++中不允许重载 ::、.*、. 、? :、sizeof运算符
上一节中,我们通过了两个全局友元函数进行了运算符重载,并且简单说明了如何进行类成员函数的运算符重载,这里首先将全局重载函数改写为成员重载函数!
示例:
#include <iostream> using namespace std; class Complex { private: int a; int b; public: Complex(int i = 0, int j = 0) { a = i; b = j; } //成员函数操作符重载 Complex operator+ (const Complex& rb); friend ostream& operator<< (ostream& out,const Complex& rc); }; //“+”号运算符为双目运算符,所以重载参数有两个,且只能有两个,但是如果该重载函数为类的 //成员函数,那么就只能有一个显示的参数,因为会有一个隐藏的this指针参数 Complex Complex::operator+ (const Complex& rb) { Complex ret; ret.a = this->a + rb.a; ret.b = this->b + rb.b; return ret; } //这里返回类型为ostream类对象的引用,是为了函数调用完成后,还能继续使用cout对象 //比如:cout << c3 << endl; ==> (cout << c3) << endl; //如果返回值不为ostream&,那么该调用会失败! ostream& operator<< (ostream& out, const Complex& rc) { out << rc.a << " + " << rc.b << "i"; return out; } int main() { Complex c1(5, 2); Complex c2(4, 9); Complex c3 = c1 + c2; //等价于:c1.operator+(c2); cout << c3 << endl; //等价于:operator<<(cout,c3); cout << "Press any key to continue..." << endl; cin.get(); return 0; }
思考:
什么时候使用全局函数重载操作符?什么时候使用成员函数重载操作符?
当无法修改左操作数的类的实现时,使用全局函数进行重载,用这种方法也能对原有的类进行功能扩展,即使我们没有源代码
C++规定,=, [], ()和->操作符只能通过成员函数进行重载
2、类的默认操作符重载
C++编译器会为每个类提供默认的赋值操作符,既是拷贝构造函数
默认的赋值操作符只是做简单的值复制
类中存在指针成员变量时就需要重载赋值操作符,因为一旦只进行简单的值复制,那么两个对象的的成员变量就同时指向了同一内存空间,这就会引发问题,比如,b对象是a对象的拷贝,如果a对象被析构,那么它申请的内存空间会被释放,而b对象此时正“使用”着该内存空间!
3、“++”和“–”运算符的重载
这两个操作符只有一个操作数
这两个操作符有前缀和有后缀的区分
思考:
那么,如何重载这两个操作符才能区分前置运算和后置运算??
答案:
可以通过占位参数来实现,因为操作符的重载本质上还是函数的重载,所以可以用参数的不同来区分两者,这里实现“++”运算符的重载来举例说明!
示例:
#include <iostream> using namespace std; class Complex { private: int a; int b; public: Complex(int i = 0, int j = 0) { a = i; b = j; } //成员函数操作符重载 Complex operator+ (const Complex& rb); friend ostream& operator<< (ostream& out,const Complex& rc); Complex operator++ (int); //obj++ Complex& operator++ (); //++obj }; //“+”号运算符为双目运算符,所以重载参数有两个,且只能有两个,但是如果该重载函数为类的 //成员函数,那么就只能有一个显示的参数,因为会有一个隐藏的this指针参数 Complex Complex::operator+ (const Complex& rb) { Complex ret; ret.a = this->a + rb.a; ret.b = this->b + rb.b; return ret; } //这里返回类型为ostream类对象的引用,是为了函数调用完成后,还能继续使用cout对象 //比如:cout << c3 << endl; ==> (cout << c3) << endl; //如果返回值不为ostream&,那么该调用会失败! ostream& operator<< (ostream& out, const Complex& rc) { out << rc.a << " + " << rc.b << "i"; return out; } //为了与内置版本保持一致,后置运算符应该返回对象的原值,返回一个值而非引用 //为了同时重载前置和后置运算符,后置版本接受一个额外的(不被使用)int类型的形参,当我们使用后置运算符时,编译器为这个形参提供一个值为0的实参 Complex Complex::operator++ (int) //obj++ { cout << "obj++" << endl; Complex temp = *this; this->a++; this->b++; return temp; } //这里返回值使用引用是为了和内置版本保持一致 Complex& Complex::operator++ () //++obj { cout << "++obj" << endl; this->a++; this->b++; return *this; } int main() { Complex c1(5, 2); Complex c2(4, 9); Complex temp = c2++; //等价于: temp = c2; c2.operator++(int); temp = ++c2; //等价于: c2.operator++(); temp = c2; (++c2)++; Complex c3 = c1 + c2; //等价于:c1.operator+(c2); cout << c3 << endl; //等价于:operator<<(cout,c3); cout << "Press any key to continue..." << endl; cin.get(); return 0; }
4、不应该被重载的运算符
最好不要去重载”&&”、”||” 和 “,” 运算符,原因如下:
&&和||内置实现了短路规则
“,”号运算符的重载版本无法保证它原有的求值顺序
操作符重载是靠函数重载来完成的
操作数作为函数参数传递
C++的函数参数都会被求值,无法实现短路规则
5、不能被重载的运算符
‘::’ – 作用域运算符
‘.*’ – 成员指针运算符
‘.’ – 成员运算符
‘? :’ – 条件运算符
‘sizeof’ – sizeof运算符
TIPS:
”.*/->*” – 成员指针运算符的使用举例
#include <iostream> using namespace std; class CTEST { public: double data; public: CTEST(double x) { data = x; } double fx(double x) { return data*data-x; } }; int main() { CTEST obj(3.14); //定义一个类对象 CTEST *p = &obj; //定义一个对象指针,并指向obj对象 double CTEST::*ip; //定义一个类成员变量指针,注意和 double *ip; 区分 ip = &CTEST::data; //让ip指针指向一个类成员变量,注意和 ip = &obj.data; 区分 cout << "obj.*ip = " << obj.*ip << endl; //通过对象名使用成员变量指针访问 cout << "obj.data = " << obj.data << endl; //普通的成员变量访问 cout << "p->*ip = " << p->*ip << endl; //通过对象指针使用成员变量指针访问 cout << "p->data = " << p->data << endl; //普通的成员变量访问 double (CTEST::*fp)(double); //定义一个类成员函数指针,注意和 double (*fp)(double); 区分 fp = &CTEST::fx; //让fp指向类成员函数,这里得显示取地址,注意和 fp = &obj.fx; 区分 cout << "(obj.*fp)(0.5) = " << (obj.*fp)(0.5) << endl; cout << "obj.fx(0.5) = " << obj.fx(0.5) << endl; cout << "(p->*fp)(5.5) = "<< (p->*fp)(5.5) << endl; cout << "(p->fx)(5.5) = " << (p->fx)(5.5) << endl; return 0; }
6、小结
操作符重载可以直接使用类的成员函数实现
=, [], ()和->操作符只能通过成员函数进行重载
++操作符通过一个int参数进行前置与后置的重载
C++中不要重载&&、|| 和 , 操作符
C++中不允许重载 ::、.*、. 、? :、sizeof运算符
相关文章推荐
- C# 格式化字符串
- WordPress网站设置搜索引擎关键词和描述
- C语言基础知识之(二):分支
- 阿里淘宝知名工程师
- Effective C++ 条款15 在资源管理类中提供对资源的原始访问
- Apache Shiro 开源权限框架
- 万网空间PHP网页设置SMTP发送评论功能
- 集合类说明及区别
- kafka笔记(PacktPub.Apache.Kafka)
- 线程的创建和生命周期
- WordPress后台没有链接管理如何添加友链?
- 一个合格的程序员应该读过哪些书
- 新增的主体结构元素
- Struts2整合Spring Hibernate的CRUD实例
- JAVA gc垃圾回收机制
- uva 816 - Abbott's Revenge(有点困难bfs迷宫称号)
- Andrew Ng机器学习课程6
- 短线
- 纯HTML5制作围住神经猫游戏-附源码下载
- iOS开发——网络篇——文件下载(NSMutableData、NSFileHandle、NSOutputStream)和上传、压缩和解压(三方框架ZipArchive),请求头和请求体格式,断点续传Range