(转)c++的运算符重载

1.前置运算符和后置运算符,左值和右值。

其实很久以来一直都没有怎么搞清楚左值和右值的区别,只知道左值可以放在等号的左边,也可以放在等号的右边,但是右值却只能放在等号的右边,然后形成一个大概直观的印象,知道怎么样做才不出错而已。不过今天看看C++,却发现有了点新的体会。

对于表达式a--=5;这样一个表达式,明显是错误的,究其原因,是因为执行等号左边的自减表达式之后,显示取得a的值,然后才是进行自减操作,所以最终的结果是一个右值,而且就是a的值(变化前的),于是对于赋值语句 b = a--,自然不会弄错了。

而对于--a=5;这样一个表达式,则明显就不同了。首先执行的是自减操作,然后返回的是a的值(变化后的),于是自然就可以将返回的a值再次赋值 了。也就是说前置的运算符是左值表达式,而后置的则是右值表达式。于是,我想到了很久前的一个想法:++a++ = 5;当然,行家肯定一看就知道是错误的,可是错误的地方需要改正啊。于是我想到了几种方法,就是通过加括号的方法来实现。

1)++(a++) = 5; 其实通过错误信息就可以看到原因了:error: non-lvalue in increment ,明显说明在自增运算符中的那个表达式不是左值,所以不能自增运算了。哦,对啊,a++是右值,于是的话再次进行++的操作就是错误的,因为++操作需要 的表达式是左值表达式。于是此处的方法行不通。

2)(++a)++ = 5;此处也不行,错误信息就是: error: non-lvalue in assignment,通过前面的表述就知道了,其实++a是左值表达式,那么后面的那个++操作就是一个错误了,赋值的时候,等号的左边不是左值表达 式,因为括号外的是一个后置的++运算符。于是,就得到了错误。

通过上面的这些折腾,对于++++a等等变态的表达式,相信也就有更深刻的体会了。

2.重载前置++和后置++的时候的不同

相信很多人都做过这种操作了,对于后置的++,需要多一个形参int来说明,但是从上面的分析,还需要注意的是两者的左值和右值的区别,重载的目 的,也不过是为了更加符合用户的习惯,于是,我们对于前置的++,自然要返回的是左值表达式,而对于后置的++,需要返回的则是左值表达式。当然,具体的 来说说吧。

前置++:如果自定义了一个类A(含有一个数据成员x),那么要重载它的前置++运算符,根据习惯,首先就是对它的数据成员++,然后再返回它的引 用,这样,才是左值表达式,于是下面的代码: A& A::operator++(){ ++x; return *this ; }这样的方法,自然很好的表达了前置的作用,先运算,在返回值。

后置++:如果同上面的例子,要定义后置++的话,那么需要注意的是它的右值性,此时是返回引用还是类类型呢?思考了很久,一般来说,返回的是引用的,都是左值表达式,而如果此处返回的是引用,那么就可能在后面的代码中出现问题。

于是出现了下面的这样的代码:

A A::operator++(int )

{

return A(this->x++);

}

其实我觉得此句甚好,既表达了后置的意思,又成功的返回了值。后置的含义,也就是先返回之后再进行自增操作,于是,此处调用的是默认的拷贝构造函数来实现返回一个临时的变量。

3.重载函数的参数问题

以前的时候被这个问题纠结的不行了,后来明白了一点,今天看看书,明白的更多了,现在才明白古人那句“书读百遍,其义自见”的至理名言了。也更加的明白了读书的重要性。

对于运算符重载,我们常用的,既可以作为成员函数,也可以作为普通函数,这点都知道,而且,此时的参数不同,作为成员函数的话,因为在类中,所以有 一个隐藏的this指针,于是,双目运算符就只要写出来一个就可以,而单目运算符就不需要写出来。同样的是一个重载运算符,可以有两种表示的方法,如:A operator+(A&, int value); //此为普通的函数       A A::operator+(int value) ;  //此为成员函数

对于上面的这两个典型的例子,很容易而直白的理解,在调用的时候,写下 a + 5; 其中a是A类型的变量,这样就OK了。但是深入思考下,重载的是+运算符,那么,双目的运算,那两个参数的顺序是,如何区分呢?很简单,前面的那个操作符 就是第一个操作符,而后面的那个就是第二个运算符。对于是成员的函数,那么就要注意this指针的作用,所以也就说明指代的对象的重要性了。为何我这么简 单的东西还要思考呢?因为被我们书上的一个变态程序搞懵了,如下:

#include <iostream>
using namespace std;
struct A{
    int a;
    A(int x){a = x;}
};

class B{
    A x;
public:
    A *operator->();
    B(int v):x(v){}       
};

A *B::operator->(){
    return &x;
}

int main()
{
   B b(5);
   int i = b->a;
   b->a = i+5;
   i = (*b.operator->()).a;
}

各位可以看看,其实道理很简单,不过是重载了->,而且重载的比较变态,让人有点琢磨不透而已。对于箭头运算符,一般的左边为指针,不过这里
重载的话左边为一个类对象,注意看声明时在B中的,所以左边的那个就是B类型的变量,也就是b,而这个是单目运算符,于是重载之后返回的指针,照理说应该
是b->
–>a,因为左边做了操作之后返回的是指针,然后再访问a,不过应该是这里的编译器处理或者规定,所以就只剩下了一个->,从此处,我看出来
了重载的参数顺序,以及参数的个数。以前总是手动的加上个参数,或者少一个,现在将this算入其中,然后看是否为成员,就可以得到确定的数目,然后就可
以知道具体的调用顺序了。

http://www.360doc.com/content/10/0907/23/1173434_51991407.shtml

(转)c++的运算符重载

时间: 2024-08-02 01:31:16

(转)c++的运算符重载的相关文章

关于运算符重载

运算符重载需遵循以下原则: 1.除了类所属关系运算符".".成员指针运算符".*".作用域运算符"::".sizeof运算符.三目运算符"?:"之外,C++中所有的运算符都可以进行重载 2.重载运算符限制在C++已有的运算符范围内,不允许创建新的运算符 3.重载之后的运算符不能改变运算符的优先级和结合性,也不能改变运算符的操作数的个数及语法结构 4.运算符重载不能改变运算符用于内置类型的对象的含义,只能用于自定义类型对象之间,

运算符重载

关键字:operator 相见:<高质量程序设计指南> P255 如果运算符被重载为全局函数,那么只有一个参数的运算符叫做一元运算符,有两个参数的运算符叫做二元运算符. 如果运算符被重载为类的成员函数,那么一元运算符没有参数(但是++和--运算符的后置版本除外),二元运算符只有右侧参数,因为对象自己成了左侧参数. 运算符重载的特殊性 如果重载为成员函数,则this对象发起对它的调用 如果重载为全局函数,则第一个参数发起对它的调用 禁止用户发明该语言运算符集合中不存在的运算符 除了函数调用运算符

C++ 运算符重载

C++中预定义的运算符的操作对象只能是基本数据类型,实际上,对于很多用户自定义类型,也需要有类似的运算操作.比如对象a和对象b, 那么 a+b 就需要用户自己定义它怎么相加,这时就用到了运算符重载. 运算符重载规则如下: ①. C++中的运算符除了少数几个之外,全部可以重载,而且只能重载C++中已有的运算符. ②. 重载之后运算符的优先级和结合性都不会改变. ③. 运算符重载是针对新类型数据的实际需要,对原有运算符进行适当的改造.一般来说,重载的功能应当与原有功能相类似,不能改变原运算符的操作对

Kotlin中复合赋值(+=,-=,……)运算符重载

本篇建立在已经了解了kotlin中运算符重载的理念以及如何实现的基础上. 来我们首先写一个简单的类,然后重载运算符+,+=,-,-=这个几个运算符.代码如下: data class Point(var x: Int, var y: Int) { operator fun plus(point: Point): Point { return Point(this.x + point.x, this.y + point.y) } operator fun plusAssign(point: Poin

第十章 运算符重载

第十章 运算符重载 1.运算符重载的方法 (实质:函数重载) *一般格式: 函数类型名operator 运算符名称(参数表){函数体:} 2.运算符重载的规则 *不允许定义新的运算符 *允许重载的运算符 双目运算符 +(加法)  - (减法)  * (乘法) / (除法)   %(取模) 关系运算符 ==(等于) != (不等)  <   >   <=   >= 逻辑运算符 ||(或)   && (与)  !(非) 单目运算符 + (正)  -(负)   *(指针)

C++运算符重载的妙用

运算符重载(Operator overloading)是C++重要特性之中的一个,本文通过列举标准库中的运算符重载实例,展示运算符重载在C++里的妙用.详细包含重载operator<<,operator>>支持cin,cout输入输出.重载operator[],实现下标运算.重载operator+=实现元素追加:重载operator()实现函数调用.假设你对C++的运算符重载掌握的游刃有余.那就无需继续往下看了. 运算符重载带来的优点就是--让代码变得简洁.以下将展示几个标准库因使

网易云课堂_C++开发入门到精通_章节4:运算符重载

课时23运算符重载 运算符重载 重载赋值运算符 Person& Person::operator=(const Person& other) { //检查自赋值 if (this == &other) { return *this; } //释放原有的内存资源 delete[]m_data; int length = strlen(other.m_data); m_data = new char[length + 1]; strcpy(m_data, other.m_data);

关于c++的运算符重载那些事

搞c++有一段时间了,今天突然要重载一个运算符,发现自己有点忘了,遂查查资料做一下c++运算符重载的小总结. 一.何为运算符重载 运算符的重载是c++语言特有的,java什么的是没有运算符重载的,所以运算符重载在笔试面试中有可能成为c++的高频考点.运算符重载就是重新定义运算符的意义,如常用的+,-,×,÷都是可以重载的.运算符重载使用的是关键字operator,表现形式是:                                                            

C++:运算符重载函数之&quot;++&quot;、&quot;--&quot;、&quot;[ ]&quot;的应用

5.2.5 "++"和"--"的重载 对于前缀方式++ob,可以用运算符函数重载为: ob.operator++() //成员函数重载 或 operator++(X &ob) //友元函数重载,其中ob为类X的对象的引用 对于后缀方式++ob,可以用运算符函数重载为: ob.operator++(int) //成员函数重载 或 operator++(X &ob,int) //友元函数重载,其中ob为类X的对象的引用 调用时,参数int一般被传递给值0

C++:运算符重载函数之成员运算符重载函数

5.2.3 成员运算符重载函数 在C++中可以把运算符重载函数定义为某个类的成员函数,称之为成员运算符重载函数. 1. 定义成员运算符重载函数的语法形式 (1)在类的内部,定义成员运算符重载函数的格式如下: 函数类型 operator 运算符(形参表) {       函数体 } (2)成员运算符重载函数也可以在类中声明成员函数的原型,在类外定义. 在类的内部,声明成员运算符重载函数原型的格式如下: class X{      ...      函数类型 operator运算符(参数表); };