c++教程类与对象自定义类中的运算符.docx
《c++教程类与对象自定义类中的运算符.docx》由会员分享,可在线阅读,更多相关《c++教程类与对象自定义类中的运算符.docx(23页珍藏版)》请在冰豆网上搜索。
c++教程类与对象自定义类中的运算符
7章类与对象
7.1类和对象(定义及使用)初步
7.2成员函数的重载
7.3对象的初始化、构造函数与析构函数
7.4类的定义及其使用
7.5类的静态成员及常量成员
7.6友元
7.7类之间的对象关系对象成员和嵌套
7.8自定义类中的运算符重载
7.8.1运算符重载的基本概念及运算符重载的两种方式
重载运算符是C++的一个重要特性.运算符重载从另一方面体现了OOP技术的多态性,即同一运算符可根据不同的运算对象完成不同的操作.
运算符重载也是函数名重载的一种特殊情况,即将运算符看成是一种特殊的函数,但其实现和使用与函数重载的实现和使用有一定的差别.
下面详细介绍运算符重载的基本方法.
7.8.1.1基本概念和方法
1.运算符重载概念
重载运算符时,可以将该运算符看成是函数名(不是真正的函数名,因为它不符合标识符的要求),然后在相应的类中定义一个与该运算符同名的函数,并告诉编译器,当遇到该重载运算符的调用时,由这个函数来完成该运算符应该完成的操作.这种函数称为运算符重载函数.它通常是类的成员函数或者友元函数..
此外,注意(对重载运算符的限制):
1)但有些运算符只能用成员函数重载,比如:
赋值运算符、数组下标运算符“[]”、函数调用运算符“()”、new、delete等
2)在C++中,大多数系统预定义的运算符都能被重载,只有少数几个运算符是不能被重载的,它们是:
.:
:
?
:
*(指针运算符)sizeof()
3)重载运算符时,不能改变它们的优先级和结合性,也不能改变这些运算符所需要操作数的个数.
4)不可自创新的运算符.
2.定义运算符重载函数的一般格式为:
<类型>operator@(<参数表>)//利用成员函数重载
{……}//函数体
或
friend<类型>operator@(<参数表>)//利用友员函数重载
{……}//函数体
其中:
1)<类型>:
为该函数的返回的类型,可以是用户自定义类型或基本数据类型,也可以是
任一导出数据类型.
2)operator:
是关键字,它与其后的运算符一起构成函数名.
3)@:
为要重载的运算符;
4)<参数表>:
为函数的形参表
①当使用类的公有成员函数重载运算符时
总以当前调用者对象(*this)作为该成员函数的隐式第一运算分量,若所定义的运算多于一个运算对象时,才将其余运算对象显式地列在该成员函数的参数表中.
②当使用类的友元函数重载运算符时
所有运算分量必须显式地列在本友元函数的参数表中,而且这些参数类型中至少要有一个应该是说明该友元的类类型或是对该类的引用.
5)由于运算符重载函数的函数名是以特殊的关键字开始的,编译器很容易与其他的函数名区分开来.
3.单目运算符重载
单目运算符只有一个操作数,
下面分别说明如何用成员函数和友元函数实现单目运算符的重载.
1)利用成员函数重载
用成员函数实现一个单目运算符重载的一般格式为:
<类型>operator<单目运算符>()
{……}//函数体
这种方法中的运算符重载函数没有任何参数(后置运算符++、——例外,将后面介绍它们).
该重载的操作数为该重载运算符所在的当前对象.
在使用该重载的运算符时,操作数一般为用户自定义类型的对象.
2)利用友元函数重载
由于友元函数不能使用*this指针,因此用友元函数重载单目运算符时必须带有一个参数作为该运算符的操作数.
重载类X的单目运算符的一般格式为:
friend<类型>operator<单目运算符>(x&obj)
{---}//函数体
1)该运算符重载函数是类X的友元.
2)obj为类X的实例,为该重载运算符的操作数.
3)对于要改变操作数的运算符(如++、--等),参数必须是引用类型或指针类型,对于不改变操作数的运算符(比如正号、符号等),参数不必为引用类型或指针类型.
4.二目运算符重载
可以用成员函数重载也可以用友元函数重载.但重载格式与单操作数不同.
1).利用成员函数重载
用成员函数重载二目运算符的格式为:
<类型>operator<二元运算符>(<参数>)
{---}//函数体
其中:
<参数>只有一个,通常为运算符的右操作数.重载二目运算符的左操作数为当前对象.
2).利用友元函数重载
用友元函数重载类X的二目运算符的一般格式:
friend<类型>operator<二元运算符>(<参数1>,<参数2>)
{---}//函数体
1)该运算符重载为类X的友元函数.
2)必须有两个参数,且至少有一个参数为X类型的实例.其中<参数1>为左参数,
而<参数2>为右操作数.
5.“++”和“——”运算符的重载
由于运算符“++”、“--”具有前置和后置两种形式,因此在对它们进行重载时要区别对待.下面仅以“++”为例说明其两种形式的重载的实现的方法,“--”的重载类似.
1)重载前置运算符的一般格式为:
<类型>operator++()
{---}//函数体
或
friend<类型>operator++(X&)
{---}//函数体
2)重载后置运算符的一般格式为:
<类型>operator++(int)
{---}//函数体
或
friend<类型>operator++(X&,int)
{---}//函数体
其中
①运算符重载函数为类X的友元.
②前置和后置的区别为:
后置运算符重载函数比前置运算符重载函数多了一个整数参数.该参数没什么特别的意义,只是标识重载的是后置运算符.
③当用友元函数重载时,X类型的参数必须为指针类型或引用类型.
7.8.1.2运算符重载示例
1)二目运算符重载
例1.利用成员函数重载二目运算符
#include
classCThree_d
{intx,y,z;
public:
CThree_d(intvx,intvy,intvz)//构造函数
{x=vx;y=vy;z=vz;}
CThree_d(){x=0;y=0;z=0;}//无参数的构造函数
CThree_doperator+(CThree_dt);//重载加号"+"
CThree_doperator-(CThree_dt);//重载减号"-"
CThree_doperator=(CThree_dt);//重载赋值符"="
voidPrint(){cout<};
CThree_dCThree_d:
:
operator+(CThree_dt)//定义两个对象的"+"运算
{
CThree_dte;
te.x=x+t.x;
te.y=y+t.y;
te.z=z+t.z;
returnte;//返回当前对象与对象之和
}
CThree_dCThree_d:
:
operator-(CThree_dt)//定义两个对象的"-"运算
{CThree_dte;
te.x=x-t.x;
te.y=y-t.y;
te.z=z-t.z;
returnte;////返回当前对象与对象之差
}
CThree_dCThree_d:
:
operator=(CThree_dt)//将对象的值赋值给当前对象
{x=t.x;
y=t.y;
z=t.z;
return*this;
}
voidmain(void)
{CThree_dt1(10,10,10),t2(20,20,20),t3;
t3=t1+t2;//At1与t2相加给t3;可以理解为:
t3=t1.+(t2),
//这里的"+"为对象t1中的重载运算符,而t2为该重载运算符的参数.
t3.Print();//显示t3对象的数据成员
t3=t2=t1;//将t1对象多重赋值给t2和t3
t1.Print();//显示t1,t2,t3的数据成员
t2.Print();
t3.Print();
}
/*
执行结果:
3030
1010
1010
1010
*/
例2.利用友元函数重载二目运算符
定义一个复数CComplex,在CComplex中包含两个数据成员,即复数的实数部分real和复数的虚数部分imag.用友元函数对该类的加、减、乘、除四个运算符进行重载.
#incluce
classCComplex//定义复数类
{floatreal,imag;//复数的实部和虚部
public:
CComplex(floatr,floati){real=r;imag=i;}//带参数的构造函数
CComplex(){real=0;imag=0}//不带参数的构造函数
voidPrint();//复数的输出函数
friendCComplexoperator+(CComplexa,CComplexb);//用友元函数重载复数相加运算符
friendCComplexoperator-(CComplexa,CComplexb);//重载复数相减运算符
friendCComplexoperator*(CComplexa,CComplexb);//重载复数相乘运算符
friendCComplexoperator/(CComplexa,CComplexb);//重载复数相除运算符
};
voidCComplex:
:
Print()
{cout<if(imag>0)cout<<”+”;
if(imag!
=0)cout<}
CComplexoperator+(CComplexa,CComplexb)
{CComplextemp;
temp.real=a.real+b.real;
temp.imag=a.imag+b.imag;
returntemp;
}
CComplexoperator–(CComplexa,CComplexb)
{CComplextemp;
temp.real=a.real–b.real;
temp.imag=a.imag–b.imag;
returntemp;
}
CComplexoperator*(CComplexa,CComplexb)
{CComplextemp;
temp.real=a.real*b.real-a.imag*b.imag;
temp.imag=a.real*b.imag+a.imag*b.real;
returntemp;
}
CComplexoperator/(CComplexa,CComplexb)
{
CComplextemp;
floattt;
tt=1/(b.real*b.real+b.imag*b.i