分享
 
 
 

C++运算符重载函数基础及其值返回状态

王朝c/c++·作者佚名  2008-06-01
窄屏简体版  字體: |||超大  

运算符重载是C++的重要组成部分,它可以让程序更加的简单易懂,简单的运算符使用可以使复杂函数的理解更直观。

对于普通对象来说我们很自然的会频繁使用算数运算符让他们参与计算,但是对于自定义类的对象来说,我们是无论如何也不能阻止写出像下面的代码一样的程序来的。

例子如下:

class Test

{

//过程省略

}

int main()

{

Test a,c;

c=a+a;

}

当然这样的代码是不能够通过编译的,c++对自定类的算术运算部分保留给了程序员,这也是符合c++灵活特性的。

在c++中要想实现这样的运算就必须自定义运算符重载函数,让它来完整具体工作。

在这里要提醒读者的是,自定义类的运算符重载函数也是函数,你重载的一切运算符不会因为是你自己定义的就改变其运算的优先级,自定义运算符的运算优先级同样遵循与内部运算符一样的顺序。

除此之外,c++也规定了一些运算符不能够自定义重载,例如.、::、.*、.->、?:。

下面我们来学习如何重载运算符,运算符重载函数的形式是:

返回类型 Operator 运算符符号 (参数说明)

{

//函数体的内部实现

}

运算符重载函数的使用主要分为两种形式,一种是作为类的友元函数进行使用,另一种则是作为类的成员函数进行使用。

下面我们先看一下作为类的友元函数使用的例子:

//程序作者:管宁

//站点:www.cndev-lab.com

//所有稿件均有版权,如要转载,请务必闻名出处和作者

#include <iostream>

using namespace std;

class Test

{

public:

Test(int a = 0)

{

Test::a = a;

}

friend Test operator +(Test&,Test&);

friend Test& operator ++(Test&);

public:

int a;

};

Test operator +(Test& temp1,Test& temp2)//+运算符重载函数

{

//cout<<temp1.a<<"|"<<temp2.a<<endl;//在这里可以观察传递过来的引用对象的成员分量

Test result(temp1.a+temp2.a);

return result;

}

Test& operator ++(Test& temp)//++运算符重载函数

{

temp.a++;

return temp;

}

int main()

{

Test a(100);

Test c=a+a;

cout<<c.a<<endl;

c++;

cout<<c.a<<endl;

system("pause");

}

在例子中,我们对于自定义类Test来说,重载了加运算符与自动递增运算符,重载的运算符完成了同类型对象的加运算和递增运算过程

重载运算符函数返回类型和形式参数也是根据需要量进行调整的,下面我们来看一下修改后的加运算符重载函数。

代码如下:

//程序作者:管宁

//站点:www.cndev-lab.com

//所有稿件均有版权,如要转载,请务必闻名出处和作者

#include <iostream>

using namespace std;

class Test

{

public:

Test(int a = 0)

{

Test::a = a;

}

friend Test operator +(Test&,const int&);

public:

int a;

};

Test operator +(Test& temp1,const int& temp2)//+运算符重载函数

{

Test result(temp1.a * temp2);

return result;

}

int main()

{

Test a(100);

Test c = a + 10;

cout<<c.a<<endl;

system("pause");

}

上面修改后的例子中,我们让重载后的加运算符做的事情,事实上并不是同类型对象的加运算,而是自定义类对象与内置int常量对象的乘法运算。

值得注重的是,对于运算符重载来说,我们并不一定要用它一定要做同类型对象的加法或者是其它运算,运算符重载函数本身就是函数,那么在函数体内部我们是可以做任何事情的,但是从不违反常规思维的角度来说,我们没有必要让重载加运算的函数来做与其重载的符号意义上完全不相符的工作,所以在使用重载运算符脱离原意之前,必须保证有足够的理由。

下面我们讨论一下作为类成员函数的运算符重载函数的使用,及其函数的值返回与引用返回的差别。

下面我们先看实例,而后逐步分析。

代码如下(重要部分做了具体的注解):

//程序作者:管宁

//站点:www.cndev-lab.com

//所有稿件均有版权,如要转载,请务必闻名出处和作者

#include <iostream>

using namespace std;

class Test

{

public:

Test(int a = 0)

{

Test::a = a;

}

Test(Test &temp)

//运算符重载函数为值返回的时候会产生临时变量,临时变量与局部变量result的复制会调用拷贝构造函数,临时变量的生命周期是在拷贝构造函数运行完成后才结束,但假如运算符重载函数返回的是引用,那么不会产生临时变量,而局部变量result的生命周期在运算符重载函数退出后立即消失,它的生命周期要比临时变量短,所以当外部对象获取返回值的内存地址所存储的值的时候,获得是一个已经失去效果的内存地址中的值,在这里的值返回与引用返回的对比,证实了临时变量的生命周期比局部变量的生命周期稍长。

{

cout<<"载入拷贝构造函数"<<"|"<<temp.a<<endl;//注重这里,假如修改运算符重载函数为返回引用,这里就会出现异常,temp.a将获得一个随机值。

Test::a = temp.a;

}

~Test()//在mian()内析构的过程是result局部变量产生的

{

cout<<"载入析构函数!"<<endl;

cin.get();

}

Test operator +(Test& temp2)//+运算符重载函数

{

//cout<<this->a<<endl;

Test result(this->a+temp2.a);

return result;

}

Test& operator ++()//++运算符重载函数

//递增运算符是单目运算符,使用返回引用的运算符重载函数道理就在于它需要改变自身。

//在前面我们学习引用的单元中我们知道,返回引用的函数是可以作为左值参与运算的,这一点也符合单目运算符的特点。

//假如把该函数改成返回值,而不是返回引用的话就破坏了单目预算改变自身的特点,程序中的++(++c)运算结束后输出c.a,会发现对象c只做了一次递增运算,原因在于,当函数是值返回状态的时候括号内的++c返回的不是c本身而是临时变量,用临时变量参与括号外的++运算,当然c的值也就只改变了一次。

{

this->a++;

return *this;

}

public:

int a;

};

int main()

{

Test a(100);

Test c=a+a;

cout<<c.a<<endl;

c++;

cout<<c.a<<endl;

++c;

cout<<c.a<<endl;

++(++c);

cout<<c.a<<endl;

system("pause");

}=版权所有 软件 下载 学院 版权所有=

上例中运算符重载函数以类的成员函数方式出现,细心的读者会发现加运算和递增运算重载函数少了一个参数,这是为什么呢?

因为当运算符重载函数以类成员函数身份出现的时候,C++会隐藏第一个参数,转而取代的是一个this指针

接下来我们具体分析一下运算符重载函数的值返回与引用返回的差别。

当我们把代码中的加运算重载函数修改成返回引用的时候:

Test& operator +(Test& temp2)//+运算符重载函数

{

Test result(this->a+temp2.a);

return result;

}

执行运算符重载函数返回引用将不产生临时变量,外部的Test c=a+a; 将获得一个局部的,栈空间内存地址位置上的值,而栈空间的特性告诉我们,当函数退出的时候函数体中局部对象的生命周期随之结束,所以保存在该地址中的数据也将消失,当c对象去获取存储在这个地址中的值的时候,里面的数据已经不存在,导致c获得的是一个随机值,所以作为双目运算的加运算符重载函数是不益采用返回引用方式编写的,当然假如一定要返回引用,我们可以在堆内存中动态开辟空间存储数据,但是这么做会导致额外的系统开销,同时也会让程序更难读懂。

对于递增运算符来说,它的意义在于能够改变自身,返回引用的函数是可以作为左值参与运算的,所以作为单目运算符,重载它的函数采用返回引用的方式编写是最合适的。

假如我们修改递增运算符重载函数为值返回状态的时候,又会出现什么希奇的现象呢?

代码如下:

Test operator ++()

{

return this->a++;

}

表面上是发现不出什么非凡明显的问题的,但是在main()函数中++(++c);的执行结果却出乎意料,理论上应该是204的值,却只是203,这是为什么呢?

因为当函数是值返回状态的时候括号内的++c返回的不是c本身而是临时变量,用临时变量参与括号外的++运算,当然c的值也就只改变了一次。结果为203而不是204。

对于运算符重载函数来说,最后我们还要注重一个问题,当运算符重载函数的形式参数类型全部为内部类型的时候,将不能重载

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有