您的位置:首页 > 编程语言 > C语言/C++

C++编程思想学习——运算符重载

2012-04-12 22:05 274 查看
1、 运算符重载的实质

a) 只是函数的另外一种调用形式,只是为了语法上的方便而已。

b) 基于运算符的实质只是为了语法上的方便,所以,运算符重载不能滥用,而且只能在类中使用,只有在能使类的更加易写或者更加易读的情况下才使用运算符重载否则适得其反。同时,只能对那些C中有的运算符才能重载,对于C中没有的不能重载,重载亦不能改变运算符的优先级,不能改变运算符的参数个数,否则,运算符的重载只会引起混淆而不会带来任何方便。

2、 运算符重载的语法

a) 参数的个数:

i. 运算符是一员的还是二元的(即1个还是2个参数)

ii. 运算符被定义为全局的(对于一元为一个参数,二元为两个参数)还是成员函数(对于一元没有参数,对于二元为一个参数)。

iii. 如:一元运算符被定义为成员函数时是没有参数的,所调用的成员函数属于运算符左侧的那个对象。一元运算符的参数可以在运算符的左则也可以在运算符的右侧,如:++a与a++。二元运算符的成员函数,唯一的参数为运算符右侧的那个操作数。二元运算符的全局函数,两个参数分布在运算符的两侧。

b) 参数和返回值的选择

i. 对于仅需要度而不改变它,默认为const引用来传递。

ii. 返回值的类型取决于运算符的具体含义,如:返回值为新生的对象,如果该新生的对象不需要在外部被改变,则可以返回一个常量的对象。

iii. 对于赋值运算则需要将左值定义为一个引用,这样返回一个对于刚刚改变的对象的一个引用。

iv. 对于逻辑运算符,则需要返回一个至少为int常量的值,最好为bool。

v. 对于前缀表达式,如果对象允许改变则返回一个引用。而对于后缀表达式,有人可能会有这样的语句(a++).fun();这样a++返回的是一个临时的对象,而这个临时的对象是常量性的,所以,编译器必然会报错。

vi. 对于f(a+b)中对”+ ”的重载,因为a+b的结果必然是一个临时的常量对象。所以,无所谓在重载函数中返回什么类型的对象。但是如为:(a+b).g()则有问题了。因为a+b的结果必然为一个常量,这样g()必须为一个常量函数。

vii. 返回值优化。在函数返回如:return Integer(left.i +right.i);则并非在函数中创建了一个局部的临时对象,然后通过拷贝构造函数,最后返回给外部。编译看到这句话会直接将这个对象在外部的存储空间中建立该值得对象,所以,大大提高了效率。

3、 不常用的运算符

a) 下标运算符operator[]。运算符new
、delete以及逗号运算符。

b) 指针间接运算符’->’用于实现灵巧指针。

c) 运算符”=”重载时,只能作为成员函数而不能为友元函数重载,因为友元函数的重载为全局式的这样就相当重定义了内置的“=”,这个是编译器所不允许的。

4、 不能重载的运算符

a) Operator.:类中的成员访问运算符

b) Operator.*:成员指针间接引用

c) 不存在用户定义的运算符,将引起编译器无法决定运算符的优先级。

5、 在嵌入类与它的载体类

当在嵌入类中定义它的一个载体类的对象作为嵌入类的成员变量时,该嵌入类的成员变

量只能为载体类的引用的形式的成员变量。

6、 非成员运算符

运算符的左侧不是当前类的对象,而是别的类的对象时,即为非成员运算符的重载。如:输入、输出流:<<
和 >>。

7、 重载赋值符

a) 内置类型:重载的对象的成员都为内置的数据类型或者不包含指针时。可以以复制的方式直接复制各个成员的值。

b) 类中指针:当类中有指针时(除用引用计数外),重载赋值符一定要复制所有所有,包指针所指的内容。

c) 引用计数:当对象比较大需要很大的内存或者初始化过高,则可以采用引用技术的方式。即每当有一个对象指向它时就将该存储空间的引用数+1。删除对象时只有引用的计数为0时才将这个对象销毁。但为了避免一个对象真在写而别的对象在读或者写时引起数据的不一致性,采用写拷贝计数。即,写时先查看引用计数是否>1,若是,则在写之前拷贝这块存储单元。

d) 如果程序员未在类中对operator=进行重载编译器会自动创建一个,这个运算符模仿拷贝运算符的行为(用位拷贝),如果类中还包含对象(成员对象)或者是从别的类继承的,对于这些对象,operator=将被递归地调用。所以,如果,自己真想使用operator=重载,一定要在类中定义自己的赋值运算符重载。

8、 自动类型转换

a) 构造函数的类型转换:

i. 类中如果有一个只带一个参数(另一个类的对象或者引用)的类的构造函数,那么这个构造函数允许编译器自动地调用本构造函数,从而将参数自动地转化为一个这个类的对象。

ii. 有时这样的转化会出问题,所以,如果不想让编译器自动调用这个构造函数实现类型转化,可以在这个构造函数前面加上关键字explicit,表示本构造函数不能被编译器自动调用,而只能由程序员显示的调用,如:f(Two(one)),其中的Two(one)为以one对象为参数显式的调用Two的构造函数以产生一个Two的对象。

iii. 为目的类型进行转换

b) 运算符的类型转换

i. 可以在本类(源类)中创建一个运算符重载的成员函数,函数的命名规则为:operator+“将要转化为的类的类名,即返回的成员类型”+(),在这个函数中实现了转化的方法,返回的转换后的类的一个对象。

ii. 全局函数的运算符可以转换左右任一操作数,而成员函数的重载必须保证左侧的操作数已经处于正确的形式。将如果全局重载不会带来问题,则全局重载会带来较大的便利。

iii. 运算符重载为源类执行转换。

iv. 重载时要注意VC6.0未完全实现C++标准不能将.h文件中的成员函数重载为友元函数。

本文为个人学习C++编程思想时个人心得体会,所以,难免有不严谨之处,甚至有可能是错误的理解。如发现错误,或者疑问。欢迎提出讨论,共同学习、进步。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: