




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
精选优质文档-----倾情为你奉上精选优质文档-----倾情为你奉上专心---专注---专业专心---专注---专业精选优质文档-----倾情为你奉上专心---专注---专业C++运算符重载知识总结5.1编译时的多态性与运行时的多态性
在C++中,多态性的实现和联编(也叫绑定)这一概念有关。源程序—>编译、连接—>可执行文件这一过程时把可执行代码联编在一起的过程。其中在运行之前就完成的联编叫做静态联编,又叫前期联编;而在程序运行时才完成的联编叫动态联编,也叫后期联编。静态联编(前期联编):指系统在编译时就决定如何实现某一动作。要求在编译时就知道调用函数的全部信息。静态联编支持的多态性成为编译时多态性(静态多态性),通过函数重载(包括运算符重载)和模板实现。优点:函数调用速度很快,效率高。动态联编(后期联编):指系统在运行时动态实现某一动作。采用这种联编方式,一直要到程序运行时才能确定调用哪个函数。动态联编支持的多态性成为运行时多态性(动态多态性),通过虚函数实现。优点:提供了更好的灵活性、问题抽象性和程序易维护性。5.2运算符重载5.2.1在类外定义的运算符重载函数
为了表达上的方便,人们希望预定义的运算符(如+、-、*、/等)在特定的对象上以新的含义进行解释,如希望能够实现两个复数类的加减,这就需要通过运算符重载来解决。
C++中进行运算符重载时,必须定义一个运算符重载函数,其名字为operator,后随一个要重载的运算符。函数功能operator+加法operator-减法operator*乘法operator<小于………...例如,使两个Complex类对象相加的例子#include<iostream>usingnamespacestd;classComplex{public:
doublereal;
doubleimag;
Complex(doubler=0,doublei=0)
{
real=r;imag=i;
}};Complexoperator+(Complexco1,Complexco2)//类外定义运算符+的重载函数{
Complextemp;
temp.real=co1.real+co2.real;
temp.imag=co1.imag+co2.imag;
returntemp;}intmain(){
Complexcom1(1.1,2.2),com2(3.3,4.4),total1,total2;
total1=operator+(com1,com2);//运算符重载函数第一种调用方式,显式调用
cout<<"real1="<<total1.real<<",imag1="<<total1.imag<<endl;
total2=com1+com2;//运算符重载函数第二种调用方式,隐式调用
cout<<"real2="<<total2.real<<",imag2="<<total2.imag<<endl;
return0;}C++语言对运算符重载制定了以下一些规则:1.绝大部分运算符可以重载,不能重载的只有以下几个:.成员访问运算符.*成员指针访问运算符::作用域运算符sizeof长度运算符?:条件运算符2.只能对已有运算符进行重载,不允许用户自己定义新的运算符。3.运算符重载是针对新类型数据的实际需要,不建议改变原运算符的含义。(例如将+运算符重载为进行减法运算)4.运算符重载不能改变运算符的操作对象(即操作数)的个数。5.运算符重载不能改变运算符原有的优先级。6.运算符重载不能改变运算符原有的结合性。7.运算符重载函数的参数至少有一个是类对象(或其引用)。目的是防止用户修改用于标准类型数据的运算符性质。8.运算符重载函数可以是普通函数、类成员函数、类的友元函数。9.赋值运算符“="可以不必用户进行重载。5.2.2友元运算符重载函数1.定义友元运算符重载的语法形式1)在类的内部,形式为:
friend函数类型operator运算符(形参表)
{
函数体
}2)类内声明,类外定义,形式为:
class
X{
friend函数类型operator运算符(形参表);
};
函数类型operator运算符(形参表)
{
函数体
}2.重载为友元函数时,没有隐含的参数this指针,这样对于双目运算符,友元函数有两个参数,对于单目运算符,友元函数有一个参数。
3.以下运算符不能定义为友元运算符重载函数:赋值运算符“=”、下标运算符“[]”、函数调用运算符“()”、“->”
。5.2.3成员运算符重载函数1.定义成员运算符重载的语法形式1)在类的内部,形式为:
函数类型operator运算符(形参表)
{
函数体
}2)类内声明,类外定义,形式为:
class
X{
函数类型operator运算符(形参表);
};
函数类型X::operator运算符(形参表)
{
函数体
}2.对双目运算符而言,成员运算符重载函数的形参表中仅有一个参数,它作为运算符的右操作数,另一个操作数(左操作数)是隐含的,是该类的当前对象,它是通过this指针隐含地传递给函数的。3.对于单目运算符而言,成员运算符重载函数的参数表中没有参数,此时当前对象作为运算符的一个操作数。5.2.4成员运算符重载函数与友元运算符重载函数的比较(1)对双目运算符而言,成员运算符重载函数参数表中含有一个参数,而友元运算符重载函数参数表中含有两个参数;(2)对于单目运算符而言,成员运算符重载函数的参数表中没有参数,而友元运算符重载函数参数表中含有一个参数。(3)双目运算符一般可以被重载为友元运算符函数或成员运算符函数,但以下情况必须使用友元函数:将一个复数和一个整数相加Complexoperator+(inta){
return(real+a,imag);}若com和com1是类Complex的对象,则以下语句是对的:com1=com+100;//正确,+左侧是类对象这条语句被解释为:com1=com.operator+(100);然而以下语句就不起作用了:com1=100+com;//错误,+左侧是整数这条语句被解释为:com1=100.operator+(com);若用友元函数则不会出现这种情况。c+100成员函数:c.operator+(100)友元函数:operator(c,100)100+c成员函数:100.operator+(c)友元函数:operator+(100,c)(4)友元运算符函数和成员运算符函数的调用形式:表达式友元函数调用成员函数调用a+boperator+(a,b)a.operator+(b)++aoperator++(a)a.operator++()-aoperator-(a)a.operator-()(5)一般来说,单目运算符最好被重载为成员函数,双目运算符被重载为友元函数。运算符“=、()、[]、->”只能作为成员函数;运算符“+=、-=、/=、*=、&=、!=、%=”建议重载为成员函数。
5.2.5“++”和“--”重载
增1减1运算符是单目运算符,它们又有前缀运算符和后缀运算符两种。为了区分这两种运算,将后缀运算视为双目运算符,在参数表中插入int。运算符名成员函数形式调用形式等价调用前缀++Xoperator++()++aa.Operator++()后缀++Xoperator++(int)a++a.Operator++(0)前缀--Xoperator--()--aa.Operator--()后缀--Xoperator--(int)a--a.Operator--(0)例题:使用成员函数重载运算符“——”#include<iostream>usingnamespacestd;classThree{public:
Three(intI1=0,intI2=0,intI3=0);
voidprint();
Threeoperator--();//前缀方式
Threeoperator--(int);//后缀方式private:
inti1,i2,i3;};Three::Three(intI1,intI2,intI3){
i1=I1;i2=I2;i3=I3;}voidThree::print(){
cout<<"i1="<<i1<<",i2="<<i2<<",i3="<<i3<<endl;}ThreeThree::operator--(){
--i1;--i2;--i3;
return*this;//返回自减后的当前对象}ThreeThree::operator--(int){
Threetemp(*this);
i1--;i2--;i3--;
returntemp;//返回自减前的当前对象}intmain(){
Threeobj1(4,5,6),obj2,obj3(11,12,13),obj4;
//隐式调用
obj1.print();
--obj1;
obj1.print();
obj2=obj1--;
obj2.print();
obj1.print();
cout<<endl;
//显式调用
obj3.print();
obj3.operator--();
obj3.print();
obj4=obj3.operator--(0);
obj4.print();
obj3.print();
return0;}例题:使用友员函数重载运算符“十十”#include<iostream>usingnamespacestd;classThree{public:
Three(intI1=0,intI2=0,intI3=0);
voidprint();
friendThreeoperator++(Three&);
friendThreeoperator++(Three&,int);private:
inti1,i2,i3;};Three::Three(intI1,intI2,intI3){
i1=I1;i2=I2;i3=I3;}voidThree::print(){
cout<<"i1="<<i1<<",i2="<<i2<<",i3="<<i3<<endl;}Threeoperator++(Three&op){
++op.i3;++op.i2;++op.i1;
returnop;//}Threeoperator++(Three&op,int){
op.i3++;op.i2++;op.i1++;
returnop;//返回自减前的当前对象}intmain(){
Threeobj1(4,5,6),obj2(14,15,16);
//隐式调用
obj1.print();//显示原值
++obj1;
obj1.print();
obj1++;
obj1.print();
//显式调用
cout<<endl;
obj2.print();//显示原值
operator++(obj2);
obj2.print();
operator++(obj2,0);//后缀方式
obj2.print();
return0;}5.2.6赋值运算符“=”重载对于任意一个类,如果用户没有定义赋值运算符函数,那么系统将自动地为其生成一个默认的赋值运算符函数,例如:X&X::operator=(constX&source){
//成员间赋值
}采用默认的赋值运算符函数实现的数据成员逐一赋值的方法是一种浅层复制方法,通常,默认的赋值运算符函数是能够胜任工作的,但有些特殊情况下,如类中有指针类型时,使用缺省的赋值运算符函数会产生错误。1.指针悬挂问题#include<iostream>usingnamespacestd;classString{public:
String(char*s)
{
cout<<"Constructorcalled"<<endl;
ptr=newchar[strlen(s)+1];
strcpy(ptr,s);
}
~String()
{
cout<<"Destructorcalled.---"<<ptr<<endl;
deleteptr;
}private:
char*ptr;};intmain(){
Stringp1("book");
Stringp2("jeep");
p2=p1;
return0;}运行结果如下:ConstructorcalledConstructorcalledDestructorcalled.---bookDestructorcalled.—葺葺葺葺这是由于默认的赋值运算函数是浅层复制,只是改变指针指向,并没有另开辟一块新的内存空间,使得第二次执行析构函数时企图释放同一空间,导致对同一个内存空间进行两次释放出错。于是出现的所谓的“指针悬挂”现象.2.用深层复制解决指针悬挂问题#include<iostream>usingnamespacestd;classString{public:
String(char*s)
{
cout<<"Constructorcalled"<<endl;
ptr=newchar[strlen(s)+1];
strcpy(ptr,s);
}
~String()
{
cout<<"Destructorcalled.---"<<ptr<<endl;
deleteptr;
}
String&operator=(constString&s);private:
char*ptr;};String&String::operator=(constString&s)//定义赋值运算重载函数{
if(this==&s)return*this;//防止s=s的赋值;
deleteptr;//释放掉原区域
ptr=newchar[strlen(s.ptr)+1];//分配新区域
strcpy(ptr,s.ptr
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 土地纠纷调解合同范本
- 分体户合作合同范本
- 分包信贷装修合同范本
- 个人批发合同范本
- 低值易耗品售卖合同范本
- 卫浴建材采购合同范例
- 中外来料加工合同
- 个人简历教师自我评价
- 个人笔迹鉴定申请书
- 原纸代购合同范例
- 《研学旅行课程设计》课件-1研学课程资源选择
- 《医学心理学》教案
- 海绵城市建设技术标准 DG-TJ08-2298-2019
- 2024年2天津理工大学马克思主义基本原理概论(期末考试题+答案)
- 跟着名著《小王子》学高考英语读后续写绝佳的续写清单-高中英语作文复习专项
- 产教融合大学科技园建设项目实施方案
- 交通法律与交通事故处理培训课程与法律解析
- 广西版四年级下册美术教案
- 《换热器及换热原理》课件
- 儿童权利公约演示文稿课件
- UPVC排水管技术标准
评论
0/150
提交评论