当前位置:文档之家› 运算符重载

运算符重载

运算符重载
运算符重载

第4章运算符重载

4.1 什么是运算符重载

所谓重载,就是重新赋予新的含义。函数重载就是对一个已有的函数赋予新的含义,使之实现新功能。

运算符也可以重载。实际上,我们已经在不知不觉之中使用了运算符重载。如:+可以对int、float、double的数据进行加法运算。

现在要讨论的问题是:用户能否根据自己的需要对C++已提供的运算符进行重载,赋予它们新的含义,使之一名多用。譬如,能否用“+”号进行两个复数、两个点的相加。在C++中不能在程序中直接用运算符“+”对复数进行相加运算。用户必须自己设法实现复数相加。

例如用户可以通过定义一个专门的函数来实现复数相加。见下例。

//例4.1 通过函数来实现复数相加。

#include

using namespace std;

class Complex

{

public:

Complex(){real=0;imag=0;} //构造函数

Complex(double r,double i){real=r;imag=i;} //构造函数重载

Complex complex_add(Complex &c2); //声明复数相加的函数

void display(); //声明输出函数

private:

double real, imag;

};

Complex Complex::complex_add(Complex &c2)

{ Complex c;

c.real=real+c2.real;

c.imag=imag+c2.imag;

return c;

//以上可简写为:return Complex(real+c2.real,imag+c2.imag);

}

void Complex::display()

{ cout<<"("<

}

int main()

{ Complex c1(3,4),c2(5,-10),c3;

c3=https://www.doczj.com/doc/555816524.html,plex_add(c2);

cout<<"c1="; c1.display();

cout<<"c2="; c2.display();

cout<<"c1+c2="; c3.display();

return 0;

}

结果无疑是正确的,但调用方式不直观、太烦琐,使人感到很不方便。能否也和整数的加法运算一样,直接用加号“+”来实现复数运算呢?如c3=c1+c2;,编译系统就会自动完成c1和c2两个复数相加的运算。如果能做到,就为对象的运算提供了很大的方便。这就需要对运算符“+”进行重载定义。我们来想一下,一个整数加a+b,其实它的操作就是函数形式add(a,b)。而写成a+b的形式更简单通俗而已。所以我们对操作符也能像进行函数那样的定义。

思考:上例是用成员函数来实现的,那么用其它的函数形式能实现吗?

//例:通过友元函数来实现复数相加。

#include

using namespace std;

class Complex

{

public:

Complex(){real=0;imag=0;} //构造函数

Complex(double r,double i){real=r;imag=i;} //构造函数重载

friend Complex complex_add(Complex &c1,Complex &c2);//声明复数相加的函数

void display(); //声明输出函数

private:

double real, imag;

};

Complex complex_add(Complex &c1,Complex &c2)

{ Complex c;

c.real=c1.real+c2.real;

c.imag=c1.imag+c2.imag;

return c;

//以上可简写为:return Complex(real+c2.real,imag+c2.imag);

}

void Complex::display()

{ cout<<"("<

}

int main()

{ Complex c1(3,4),c2(5,-10),c3;

c3=complex_add(c1,c2);a

cout<<"c1="; c1.display();

cout<<"c2="; c2.display();

cout<<"c1+c2="; c3.display();

return 0;

}

通过普通函数怎么实现呢?

4.2 运算符重载的方法

运算符重载的方法是定义一个重载运算符的函数,在需要执行被重载的运算符时,系统就自动调用该函数,以实现相应的运算。也就是说,运算符重载是通过定义函数实现的。运算符重载实质上是函数的重载。

重载运算符的函数一般格式如下:函数类型operator 运算符名称(形参表列)

{ 对运算符的重载处理}

例如,想将“+”用于Complex类(复数)的加法运算,函数可以是这样的:

Complex operater+ (Complex& c1,Complex& c2);

在定义了重载运算符的函数后,可以说:函数operator+重载了运算符+。

可以在例4.1程序的基础上重载运算符“+”,使之用于复数相加。

//例4.2 重载运算符“+”

#include

using namespace std;

class Complex

{public:

Complex(){real=0;imag=0;}

Complex(double r,double i){real=r;imag=i;}

Complex operator + (Complex &c2);

void display();

private:

double real;

double imag;

};

Complex Complex::operator + (Complex &c2)

{ Complex c;

c.real=real+c2.real;

c.imag=imag+c2.imag;

return c;

}

//或简写为:{return Complex(real+c2.real,imag+c2.imag);}

void Complex::display()

{cout<<"("<

int main()

{Complex c1(3,4),c2(5,-10),c3;

c3=c1+c2; //+重载定义后可以直接用+

cout<<"c1="; c1.display();

cout<<"c2="; c2.display();

cout<<"c1+c2="; c3.display();

return 0;

}

请比较例4.1和例4.2,只有两处不同:

●在例4.2中以operator+函数取代了例4.1中的complex_add函数,而且只是函数名不同,

函数体和函数返回值的类型都是相同的。

●在main函数中,以“c3=c1+c2;”取代了例10.1中的“c3=https://www.doczj.com/doc/555816524.html,plex_add(c2);”。在将运算

符+重载为类的成员函数后,C++编译系统将程序中的表达式c1+c2解释c1.operator+(c2)

其中c1和c2是Complex类的对象,即以c2为实参调用c1的运算符重载函数

operator+(Complex &c2),进行求值,得到两个复数之和。

虽然重载运算符所实现的功能完全可以用函数实现,但是使用运算符重载能使用户程序易于编写、阅读和维护。在实际工作中,类的声明和类的使用往往是分离的。假如在声明Complex类时,对运算符+,-,*,/都进行了重载,那么使用这个类的用户在编程时可以完全不考虑函数是怎么实现的,放心大胆地直接使用+,-,*,/进行复数的运算即可,十分方便。

c1+c2就相当于c1.operator+(c2),c1+c2的书写形式更加人性化。

4.3 重载运算符的规则

重载运算符的规则如下:

1、C++不允许用户自己创建新的运算符,只能对已有的C++运算符进行重载。

2、操作个数不变、优先级不变、结合性不变

3、不能有默认的参数

4、重载运算符必须和用户定义的对象一起使用,其参数至少应有一个是类对象或类对象的

引用。也就是说参数不能全是C++的标准类型,以防用户改变了原标准类型的运算性质。

5、重载后的操作符的新意思要与原意一致。

6、基本规则(有些规则在后面的实例中会讲到)

1)一元操作符可以是不带参数的成员函数或带一个参数的非成员函数。

2)二元操作符可以是带一个参数的成员函数或带两个参数的非成员函数。

3)operator=、operator[]、operator()、operator->只能定义为成员函数。

4)operator->的返回值必须是一个指针或能使用->的对象。

5)重载operator++ 和operator-- 时带一个int 参数表示后缀,不带参数表示前缀。

6)除operator new 和operator delete 外,重载的操作符参数中至少要有一个自定义数据类型。

4.4 运算符重载函数作为类成员函数和友元函数

在我们前面举的实例中,“+”是双目运算,但我们只看到一个参数。那是因为重载函数是类中的成员函数,有一个参数是隐含的,运算符函数是用this指针隐式地访问类对象的成员。

运算符重载函数除了可以作为类的成员函数,还可以是非成员函数。

//例4.3 +重载,重载函数不作为成员函数,而是作为Complex的友员函数

#include

//VC++没有完全实现C++标准,不带后缀.h的头文件不支持操作符重载为友元函数,

//所以这里要加上.h,并删去使用名空间那句话。

class Complex

{public:

Complex(){real=0;imag=0;}

Complex(double r){real=r;imag=0;}

Complex(double r,double i){real=r;imag=i;}

friend Complex operator+ (Complex &c1,Complex &c2);

void display();

private:

double real;

double imag;

};

Complex operator+ (Complex &c1,Complex &c2)

{return Complex(c1.real+c2.real, c1.imag+c2.imag);}

void Complex::display()

{cout<<"("<

int main()

{Complex c1(3,4),c2(5,-10),c3;

c3=c1+c2;

cout<<"c1="; c1.display();

cout<<"c2="; c2.display();

cout<<"c1+c2="; c3.display();

return 0;

}

与例4.2相比较,只作了一处改动,将运算符函数不作为成员函数,而把它放在类外,在Complex类中声明它为友元函数。同时将运算符函数改为有两个参数。在将运算符“+”重载为非成员函数后,C++编译系统将程序中的表达式c1+c2解释为:operator+(c1,c2),即执行c1+c2相当于调用以下函数:Complex operator + (Complex &c1,Complex &c2)

{return Complex(c1.real+c2.real, c1.imag+c2.imag);}

求出两个复数之和。

为什么把运算符函数作为友元函数呢?因为运算符函数要访问Complex类对象中的成员。如果运算符函数不是Complex类的友元函数,而是一个普通的函数,它是没有权利访问Complex类的私有成员的。

在4.2节中曾提到过:运算符重载函数可以是类的成员函数,也可以是类的友元函数,还可以是既非类的成员函数也不是友元函数的普通函数。现在分别讨论这3种情况。

1)只有在极少的情况下才使用既不是类的成员函数也不是友元函数的普通函数,原因是上面提到的,普通函数不能直接访问类的私有成员。

//自编,用普通函数实现+重载

#include

using namespace std;

class Complex

Complex(){real=0;imag=0;}

Complex(double r){real=r;imag=0;}

Complex(double r,double i){real=r;imag=i;}

void display();

int getreal(){return real;}

int getimag(){return imag;}

private:

double real;

double imag;

};

Complex operator+(Complex &c1,Complex &c2)

{return Complex(c1.getreal()+c2.getreal(), c1.getimag()+c2.getimag());}

void Complex::display()

{cout<<"("<

int main()

{Complex c1(3,4),c2(5,-10),c3;

c3=c1+c2;

cout<<"c1="; c1.display();

cout<<"c2="; c2.display();

cout<<"c1+c2="; c3.display();

return 0;

}

因为不能直接访问私有成员,只有定义公有的getreal和getimag两个函数来读取私有数据成员。这样转了一个圈子,编程不便,运行时调用函数的降低了效率。

2)将运算符重载函数作为成员函数,如例4.2,它可以通过this指针自由地访问本类的数据成员,因此可以少写一个函数的参数。但必须要求运算表达式第一个参数(即运算符左侧的操作数)是一个类对象,而且与运算符函数的类型相同。因为必须通过类的对象去调用该类的成员函数,而且只有运算符重载函数返回值与该对象同类型,运算结果才有意义。在例4.2中,表达式c1+c2中第一个参数c1是Complex类对象,运算符函数返回值的类型也是Complex,这是正确的。如果c1不是Complex类,它就无法通过隐式this指针访问Complex 对象了。

如果想将一个复数和一个整数相加,如c1+i,可以将运算符重载函数作为成员函数,如下形式:

Complex Complex∷operator+(int &i) //运算符重载函数作为Complex类的成员函数{return Complex(real+i,imag);}

注意在表达式中重载的运算符“+”左侧应为Complex类的对象,如:c3=c2+i; 不能写成:c3=i+c2; //运算符“+”的左侧不是类对象,编译出错

//自编,复数+整数

#include

class Complex

{

private:

double real,imag;

Complex operator+(int i){return Complex(real+i,imag);}

Complex(){}

Complex(double r,double i){real=r;imag=i;}

void display()

{ i f(imag>=0)

cout<

else

cout<

}

Complex add(Complex &c)

{ return Complex(real+c.real,imag+c.imag);

}

};

int main()

{ Complex c1(1,2);

(c1+3).display();

return 0;

}

3)友元函数方式

如果出于某种考虑,要求在使用重载运算符时运算符左侧的操作数是整型量(如表达式i+c2,运算符左侧的操作数i是整数),这时是无法利用前面定义的重载运算符的,因为无法调用i.operator+函数。可想而知,如果运算符左侧的操作数属于C++标准类型(如int)或是一个其他类的对象,则运算符重载函数不能作为成员函数,只能作为非成员函数。如果函数需要访问类的私有成员,则必须声明为友元函数。可以在Complex类中声明:friend Complex operator+(int &i,Complex &c); //第一个参数可以不是类对象

在类外定义友元函数:

Complex operator+(int &i, Complex &c) //运算符重载函数不是成员函数{return Complex(i+c.real,c.imag);}

//自编,整数+复数

#include

class Complex

{

private:

double real,imag;

public:

Complex operator+(int i){return Complex(real+i,imag);}

friend Complex operator+(int i,Complex &c);

Complex(){}

Complex(double r,double i){real=r;imag=i;}

void display()

{

if(imag>=0)

cout<

else

cout<

}

Complex add(Complex &c)

{

return Complex(real+c.real,imag+c.imag);

}

};

Complex operator+(int i, Complex &c) //运算符重载函数不是成员函数{return Complex(i+c.real,c.imag);}

int main()

{

Complex c1(1,2);

(c1+3).display();

(3+c1).display();

return 0;

}

将双目运算符重载为友元函数时,在函数的形参表列中必须有两个参数,不能省略,形参的顺序任意,不要求第一个参数必须为类对象。但在使用运算符的表达式中,要求运算符左侧的操作数与函数第一个参数对应,运算符右侧的操作数与函数的第二个参数对应。如c3=i+c2; //正确,类型匹配

c3=c2+i; //错误,类型不匹配

请注意,数学上的交换律在此不适用。如果希望适用交换律,则应再重载一次运算符“+”。如

Complex operator+(Complex &c, int &i) //此时第一个参数为类对象

{return Complex(i+c.real,c.imag);}

这样,使用表达式i+c2和c2+i都合法,编译系统会根据表达式的形式选择调用与之匹配的运算符重载函数。可以将以上两个运算符重载函数都作为友元函数,也可以将一个运算符重载函数(运算符左侧为对象名的) 作为成员函数,另一个(运算符左侧不是对象名的)作为友元函数。但不可能将两个都作为成员函数,原因是显然的。

C++规定,有的运算符(如赋值运算符、下标运算符、函数调用运算符)必须定义为类的成员函数,有的运算符则不能定义为类的成员函数(如流插入“<<”和流提取运算符“>>”、类型转换运算符)。

由于友元的使用会破坏类的封装,因此从原则上说,要尽量将运算符函数作为成员函数。但考虑到各方面的因素,一般将单目运算符重载为成员函数,将双目运算符重载为友元函数。

4.5 重载双目运算符

双目运算符(或称二元运算符)是C++中最常用的运算符。双目运算符有两个操作数,通常在运算符的左右两侧,如3+5,a=b,i<10等。在重载双目运算符时,不言而喻在函数中应该有两个参数。在前面所举的例子都是两目运算的。下面再举一个例子说明重载双目运算符的应用。

下面我们来定义一个字符串String,用来存放不定长的字符串,重载运算符“==”,“<”和“>”,用于两个字符串的等于、小于和大于的比较运算。

//例4.4

//第一步:建立一个String类,具备最基本功能

#include

using namespace std;

class String

{

public:

String( ){p=NULL;} //默认构造函数

String(char *str); //构造函数重载

void display( );

private:

char *p; //字符型指针,用于指向字符串

};

String::String(char *str) //定义构造函数

{p=str;} //使p指向实参字符串

void String::display() //输出p所指向的字符串

{cout<

int main( )

{

String string1("Hello"),string2("Book");

string1.display( );

cout<

string2.display( );

return 0;

}

在有了String这个类之后,再增加其他必要的内容。现在增加对运算符重载的部分。为便于编写和调试,先重载一个运算符“>”。程序如下:

//例4.4

//第二步,定义一个运算符”>”重载

#include

#include

class String

{public:

String(){p=NULL;}

String(char *str);

friend bool operator>(String &string1,String &string2);

/*bool operator>(String s)

{

if(strcmp(p,s.p)>0)

return true;

else

return false;

}*/ //也可以用成员函数来实现

void display();

private:

char *p;

};

String::String(char *str)

{p=str;}

void String::display()

{cout<

bool operator>(String &string1,String &string2) {if(strcmp(string1.p,string2.p)>0)

return true;

else return false;

}

int main()

{String string1("Hello"),string2("Book");

cout<<(string1>string2)<

return 0;

}

程序运行结果为1。

思考:用成员函数或普通函数怎么实现?//成员函数实现

#include

using namespace std;

class String

{

char *p;

public:

String(){p=NULL;}

String(char *str){p=str;}

void display(){cout<

bool operator>(String s)

{

if(strcmp(p,s.p)>0)

return true;

else

return false;

}

};

int main()

{

String str1("Hello"),str2("hello");

str1.display();

cout<<(str1>str2)<

这只是一个并不很完善的程序,但是,已经完成了实质性的工作了,运算符>重载成功了。其他两个运算符的重载基本是一样的。

//例4.4

//第三步:重载运算符>、==

#include

#include

class String

{public:

String(){p=NULL;}

String(char *str);

friend bool operator>(String &string1,String &string2);

friend bool operator<(String &string1,String &string2);

friend bool operator==(String &string1,String &string2);

void display();

private:

char *p;

};

String::String(char *str)

{p=str;}

void String::display()

{cout<

bool operator>(String &string1,String &string2)

{if(strcmp(string1.p,string2.p)>0)

return true;

else return false;

}

bool operator<(String &string1,String &string2)

{if(strcmp(string1.p,string2.p)<0)

return true;

else return false;

}

bool operator==(String &string1,String &string2)

{if(strcmp(string1.p,string2.p)==0)

return true;

else return false;

}

int main()

{String string1("Hello"),string2("Book");

cout<<(string1>string2)<

cout<<(string1

cout<<(string1==string2)<

return 0;

//说明:该实例也可以通过成员函数和普通函数的形式实现。共三种方法。

最后还可以进一步完善程序,使得输出结果更直观。这里就不给出源程序了。见P326。

通过这个例子,不仅可以学习到有关双目运算符重载的知识,而且还可以学习怎样去编写C++程序。

这种方法的指导思想是:先搭框架,逐步扩充,由简到繁,最后完善。边编程,边调试,边扩充。千万不要企图在一开始时就解决所有的细节。类是可扩充的,可以一步一步地扩充它的功能。最好直接在计算机上写程序,每一步都要上机调试,调试通过了前面一步再做下一步,步步为营。这样编程和调试的效率是比较高的。

4.6 重载单目运算符

单目运算符只有一个操作数,如!a,-b,&c,*p,还有最常用的++i和--i等。重载单目运算符的方法与重载双目运算符的方法是类似的。但由于单目运算符只有一个操作数,因此运算符重载函数只有一个参数,如果运算符重载函数作为成员函数,则还可省略此参数。下面以自增运算符“++”为例,介绍单目运算符的重载。

我们知道,++有前后之分,使用前增量时,对对象(操作数)进行增量修改,然后再返回该对象。所以前增量运算符操作时,参数与返回的是同一个对象,这与基本数据类型的前增量操作类似,返回的也是左值。

使用后增量时,必须在增量之前返回原有的对象值。为此,需要创建一个临时对象,存放原有的对象,以便对操作数(对象)进行增量修改时,保存最初的值。后增量操作返回的是原有对象值,不是原有对象,原有对象已经被增量修改,所以,返回的应该是存放原有对象值的临时对象。返回类型是类就可以了。

C++约定,在增量运算符定义中,放上一个整数形参,就是后增量运算符。

/*例4.5

有一个Time类,包含数据成员minute和sec,模拟秒表,每次走1秒,

满60秒进一分钟。此时又从0开始算。要求输出分和秒的值

前++ */

#include

using namespace std;

class Time

{public:

Time(){minute=0;sec=0;}

Time(int m,int s):minute(m),sec(s){}

Time operator++();

void display(){cout<

private:

int minute;

int sec;

};

Time Time::operator++()

{if(++sec>=60)

{sec-=60;

++minute;}

return *this; //return Time(minute,sec);

}

int main()

{Time time1(34,0);

for (int i=0;i<61;i++)

{++time1;

time1.display();}

return 0;

}

思考:上例是用成员函数来实现,如果用友元函数、普通函数怎么实现?//上例用友元函数实现

#include

using namespace std;

class Time

{

int minute,sec;

public:

Time():minute(0),sec(0){}

Time(int m,int s):minute(m),sec(s){}

void display(){cout<

friend Time operator++(Time &t );

};

Time operator++(Time &t) //这里一定要用引用

{ t.sec++;

if(t.sec>=60)

{ t.sec-=60;

t.minute++;

}

return t;

}

int main()

{

Time t(3,59);

for(int i=1;i<=70;i++)

{

(++t).display();

}

}

用普通函数也可以实现,程序如下:

#include

using namespace std;

class Time

{

int minute,sec;

public:

Time():minute(0),sec(0){}

Time(int m,int s):minute(m),sec(s){}

void display(){cout<

int getmin(){return minute;}

int getsec(){return sec;}

};

Time operator++(Time &t)

{ int s,m;

s=t.getsec();

m=t.getmin();

s++;

if(s>=60)

{ s-=60;

m++;

}

t=Time(m,s);

return t;

}

int main()

{

Time t(3,59);

for(int i=1;i<=70;i++)

{

(++t).display();

}

}

C++约定,在增量运算符定义中,放上一个整数形参,就是后增量运算符。下面我们在上例的基础上进行后++的重载定义。

#include

using namespace std;

class Time

{public:

Time(){minute=0;sec=0;}

Time(int m,int s):minute(m),sec(s){}

Time operator++();

Time operator++(int);

void display(){cout<

private:

int minute;

int sec;

};

Time Time::operator++()

{if(++sec>=60)

{sec-=60;

++minute;}

return *this;

}

Time Time::operator++(int)

{Time temp(*this); //要返回的,前暂存起来,因为在后面会对其数据成员改变sec++;

if(sec>=60)

{sec-=60;

++minute;}

return temp;

}

int main()

{Time time1(34,59),time2;

cout<<" time1 : ";

time1.display();

++time1;

cout<<"++time1: ";

time1.display();

time2=time1++;

cout<<"time1++: ";

time1.display();

cout<<" time2 : ";

time2.display();

return 0;

}

我们看到,前++是先自加,返回修改后的对象本身。后者返回的是自加前的对象,然后对象自加。

下面来看一下我们在前面定义的Time(包括hour,minute,second)进行++运算的实例。

//==================================

// 自编,Time类的++重载

//==================================

#include

#include

//----------------------------------

class Time{

int hour, minute, second;

public:

Time(int h, int m, int s){ hour=h, minute=m, second=s; }

friend Time& operator++(Time& a); //这是前增量,返回的是类的引用

friend Time operator++(Time& a, int); //这是后增量,返回的是类

void disp(){cout<

};//-------------------------------

Time& operator++(Time& a){

if(!(a.second=(a.second+1)%60)&&!(a.minute=(a.minute+1)%60))

a.hour=(a.hour+1)%24;

return a;

}//--------------------------------

Time operator++(Time& a, int){

Time t(a);

if(!(a.second=(a.second+1)%60)&&!(a.minute=(a.minute+1)%60))

a.hour=(a.hour+1)%24;

return t;

}//------------------------------------

int main(){

Time t(11, 59, 58);

(t++).disp();

(++t).disp();

}//================================

前后增量操作的意义,决定了其不同的返回方式。前增量运算符返回引用,后增量运算符返回值。

后增量运算符中的参数int只是为了区别前增量与后增量,除此之外没有任何作用。因为定义中,无须使用该参数,所以形参名在定义头中省略。

4.7 重载流插入运算符和流提取运算符

C++的流插入运算符“<<”和流提取运算符“>>”是C++在类库中提供的,所有C++编译系统都在类库中提供输入流类istream和输出流类ostream。cin和cout分别是istream类和ostream类的对象。在类库提供的头文件中已经对“<<”和“>>”进行了重载(<<左移操作符,>>右移操作符),使之作为流插入运算符和流提取运算符,能用来输出和输入C++标准类型的数据。因此,在本书前面几章中,凡是用“cout<<”和“cin>>”对标准类型数据进行输入输出的,都要用#include 把头文件包含到本程序文件中。

用户自己定义的类型的数据,是不能直接用“<<”和“>>”来输出和输入的。如果想用它们输出和输入自己声明的类型的数据,必须对它们重载。

对“<<”和“>>”重载的函数形式如下:

istream &operator >> (istream &,自定义类&); //返回类型和第一个参数必须是istream & ostream & operator << (ostream &,自定义类&); //返回类型和第一个参数必须是ostream& 即重载运算符“>>”的函数的第一个参数和函数的类型都必须是istream&类型,第二个参数是要进行输入操作的类。重载“<<”的函数的第一个参数和函数的类型都必须是ostream&类型,第二个参数是要进行输出操作的类。因此,只能将重载“>>”和“<<”的函数作为友元函数或普通的函数,而不能将它们定义为成员函数。(因为一个操作数不是类对象)

4.7.1 重载流插入运算符<<

//例4.7 在4.2的基础上,用重载的“<<”来输出复数

#include

class Complex

{public:

Complex(){real=0;imag=0;}

Complex(double r,double i){real=r;imag=i;}

Complex operator + (Complex &c2);

friend ostream& operator << (ostream&,Complex&); //运算符<<重载为友元函数private:

double real;

double imag;

};

Complex Complex::operator + (Complex &c2)

{return Complex(real+c2.real,imag+c2.imag);}

ostream& operator << (ostream& output, Complex& c) //定义运算符<<重载函数

{output<<"("<

return output;

}

int main()

{Complex c1(2,4),c2(6,10),c3;

c3=c1+c2;

cout<

/*可以直接输出用户自己定义的类对象了,即operator<<(cout,c3)

cout是实参,output是形参,c3是实参,c是形参,代入后即执行

cout<< output<<"("<

cout<

/*return output的作用就是可以重叠操作,return output就是return cout,

((cout<

return 0;

}

//说明,如果用普通函数也能实现,但要定义可以获得数据成员的公有函数才行。

下面我们来对Point这个类来进行<<的重载

//==================================

// 自编

// 重载操作符<<

//==================================

#include

//----------------------------------

class Point{

int x, y;

public:

Point(int a, int b){ x=a, y=b; }

friend ostream& operator<<(ostream&,Point&);

friend Point operator+(const Point& a, const Point& b);

};//===============================

Point operator+(const Point& a, const Point& b)

{

return Point(a.x+b.x, a.y+b.y);

}//--------------------------------

ostream& operator<<(ostream& o,Point& a){

return o<<"("<

}//----------------------------------

int main(){

Point a(3,2), b(1,5);

cout<

cout<<(a+b);

}//================================

为什么Point的+操作返回Point类的值,而<<操作返回流的引用呢?

因为对于operator+(),两个对象相加,不改变其中任一个对象。而且它必须生成一个结果对象来存放加法的结果,并将该结果对象以值的方式返回给调用者。

而<<就不同了,cout<

通俗地讲,如果返回的值还要再用它来参加运算(改变它的值)就要返回引有,如果返回的值不用再参加运算(改变它的值)就用值方式返回。

4.7.2 重载流插入运算符>>

学习了<<的重载,再来学>>的重载就简单多了。

//例4.8 在4.7的基础上,增加>>的重载定义。

//以下只写了重载>>的部分

istream& operator>>(istream & input,Complex&c) //注意,必须是引有

{

cout<<"please input:";

input>>c.real>>c.imag;

return input;

}

同样的道理,>>也可以重叠操作。

4.8 不同类型数据间的转换

4.8.1 标准类型数据间的转换

在C++中,某些不同类型数据之间可以自动转换,例如5/8与5.0/8结果不同,原因是C++执行了两种不同的操作。5.0/8匹配了两个double类型数的除法,C++知道如何将8转换成double型,这是基本数据类型的转换。这种转换是C++编译系统自动完成的,用户不需干预。这种转换称为隐式类型转换。

C++还提供了显式转换,其形式为:类型名(数据)

4.8.2 用转换构造函数进行类型转换

转换用户定义的类类型,必须由用户告知。用户告知的方式就是定义只包含一个参数的转换构造函数。

转换构造函数的作用是将一个其他类型的数据转换成一个类的对象。

我们前面学过以下几种构造函数,再来回顾一下。均以Complex类为例

默认构造函数:Complex();

用于初始化的构造函数:Complex(double r,double i);

用于复制对象的复制构造函数:Complex(Complex &c);

用于类型转换的转换构造函数:转换构造函数只有一个参数,如:

Complex(double r){real=r;imag=0;}其作用是将double型的参数r转换成Complex类的对象,将r作为复数的实数,虚部为0。用户可以根据需要定义转换构造函数。

//自编,将一个double的数转换为复数。

#include

class Complex

{public:

Complex(){real=0;imag=0;}

Complex(double r,double i){real=r;imag=i;}

Complex operator+(Complex &c){return Complex(real+c.real,imag+c.imag);}

friend ostream & operator<<(ostream &,Complex);

Complex(double r){real=r;imag=0;} //转换构造函数

private:

double real;

double imag;

};

ostream & operator<<(ostream & output,Complex c)

{

if(c.imag>=0)

output<<"("<

else

output<<"("<

return output;

}

int main()

{ Complex c1(3,4),c2(2,-3);

Complex c3(3.5); //建立一个对象c3,由于只有一个参数,调用转换构造函数cout<

cout<

cout<

return 0;

}

注意:转换函数只能有一个参数,如果有多个参数,肯定不是转换函数。但有一个参数的构造函数不一定就是转换构造函数。

如:Complex(double r){cout<

归纳起来,使用转换构造函数将一个指定的数据转换为类对象的方法如下:

a)先声明一个类

b)在这个类中定义一个只有一个参数的构造函数,参数的类型是需要转换的类型,在

类函数体中指定转换的方法

c)在该类的作用域内可以用以下形式进行类型转换:类名(指定类型的数据)

就可以指定类型的数据类型转换为此类的对象。

不仅可以将一个标准类型数据转换成类对象,也可以将另一个类的对象转换成转换构造函数所在的类对象。

//自编将一个学生类对象转换成教师类对象。Teacher类中写转换构造函数

#include

#include

using namespace std;

//-------------------------------------

class Student

{

public:

int num;

string name;

char sex;

Student(int i,string n,char s):num(i),name(n),sex(s){}

void display(){cout<

};//--------------------------------------------

class Teacher

{

int num;

string name;

char sex;

string bm; //比学生类多一个数据成员(部门)

public:

Teacher(){};

Teacher(int i,string n,char s,string b):num(i),name(n),sex(s),bm(b){}

运算符重载练习题.

运算符重载 一.单项选择题 1.下列运算符中,运算符在C++中不能重载。 A.?: B.+ C. D.<= 解:C++中不能被重载的运算符有:·,一,::,?:。本题答案为A。 2.下列运算符中,运算符在C++中不能重载。 A.&& B.[] C.:: D.new 解:c++中不能被重载的运算符有:·,·+,::,?:。本题答案为c。 3.下列关于运算符重载的描述中,是正确的。 A.运算符重载可以改变操作数的个数 B.运算符重载可以改变优先级 C.运算符重载可以改变结合性 D.运算符重载不可以改变语法结构 解:运算符重载不能改变操作数的个数、运算符的优先级、运算符的结合性和运算程的语法结构。本题答案为D。 4.友元运算符objl>obj2被C++编译器解释为。 A.operator>(objl,obj2) B.>(obj1,obj2) C.obj2.operator:>(obj1) D.objl.operator>(obj2) 解:重载为友元函数的运算符的调用形式如下: operator<运算符>(<参数1>,<参数2>) 等价于:<参数1><运算符><参数2> 本题答案为A。 5.现需要对list类对象使用的逻辑运算符“==”重载,以下函数声明是正确的。 A、list & list::operator==(const list &a); B、list list::operator==(const list &a); C、bool & list::operator==(const list &a); D、bool list::operator==(const list &a); 6. 以下类中分别说明了“+=”和“++”运算符重载函数的原型。如果主函数中有定义: fun m,c,d;,那么,执行语句c=m++; 时,编译器把m++解释为: (33) A) c.operator++(m); B) m=operator++(m); C) m.operator++(m); D) operator++(m); class fun { public: .. .. .. fun operator +=(fun ); friend fun operator ++(fun &,int); }; 答案:D 7. 在第33题中,当执行语句d+=m; 时,C++编译器对语句作如下解释: (34) A. d=operator+=(m); B. m=operator+=(d); C. d.operator+=(m); D. m.operator+=(d); 答案:C 8. 设有以下类定义,其中说明了“+”运算符重载函数的原型。这是一个友元函数,当类

运算符重载知识题

. 《面向对象程序设计》习题 班级:学号:姓名:名单序号:成绩: 第7章运算符重载和多态性 一、选择题(共30分,每题1分) 1.下列运算符中,()运算符在C++中不能重载。 A.?: B.[] C. new D.++ 2.友元重载运算符obj1>obj2被C++编译器解释为()。 A.operator >(obj1,obj2) B.>(obj1,obj2) C.obj2.operator >(obj1) D.obj1.operator >(obj2) 3.重载赋值操作符时,应声明为()函数。 A.友元B.虚C.成员D.多态 4.在重载一个运算符时,其参数表中没有任何参数,这表明该运算符是()。 A. 作为友元函数重载的1元运算符 B. 作为成员函数重载的1元运算符 C. 作为友元函数重载的2元运算符 D. 作为成员函数重载的2元运算符5.在重载一运算符时,若运算符函数的形参表中没有参数,则不可能的情况是()。 A. 该运算符是一个单目运算符。 B. 该运算符函数有一个隐含的参数this。 C. 该运算符函数是类的成员函数。 D. 该运算符函数是类的友元函数。 6. 关于运输符重载,下列表述中正确的是()。 A.C++已有的任何运算符都可以重载 B.运算符函数的返回类型不能声明为基本数据类型

. C.在类型转换符函数的定义中不需要声明返回类型 D.可以通过运算符重载来创建C++中原来没有的运算符 7. C ++流中重载的运算符>>是一个()。 A. 用于输出操作的非成员函数 B. 用于输出操作的成员函数 C. 用于输入操作的非成员函数 D. 用于输入操作的成员函数 8. 若要对Data类中重载的加法运算符成员函数进行声明,下列选项中正确的是()。 A. Data +(Data); B. Data operator+(Data); C. Data +operator(Data); D. operator +(Data, Data); 9. 下列运算符中哪些是不能够被重载的()。 A. .,.*,sizeof,::,?: B. ++,--,new,= = C. new,delete,>=,[ ] D. +,-,=,delete 10. 在名为BigNumber类的类体中对运算符函数double进行如下声明: operator double(BigNumbe); 函数声明中有一个明显的错误,这个错误就是()。 A.参数表中不应该有任何参数 B.缺少对函数返回类型的说明 C.参数声明中缺少参数变量 D.函数声明中缺少函数体 11. 下列关于运算符重载的描述中,正确的是()。 A. 运算符重载成为成员函数时,若参数表中无参数,重载是一元运算符 B. 一元运算符只能作为成员函数重载 C. 二元运算符重载成为非成员函数时,参数表中有一个参数

C++运算符重载例程详解

运算符重载就是对一个已有的运算符赋予新的含义,使之实现新功能。下面将通过简单的几个例程阐叙其用法。 例10.1 通过函数来实现复数相加。 #include using namespace std; class Complex //定义Complex类 {public: Complex( ){real=0;imag=0;} //定义构造函数 Complex(double r,double i){real=r;imag=i;} //构造函数重载Complex complex_add(Complex &c2); //声明复数相加函数void display( ); //声明输出函数private: double real; //实部 double imag; //虚部 }; Complex Complex::complex_add(Complex &c2) {Complex c; c.real=real+c2.real; c.imag=imag+c2.imag; return c;} void Complex::display( ) //定义输出函数{cout<<″(″<

int main( ) {Complex c1(3,4),c2(5,-10),c3; //定义3个复数对象c3=https://www.doczj.com/doc/555816524.html,plex_add(c2); //调用复数相加函数cout<<″c1=″; c1.display( ); //输出c1的值cout<<″c2=″; c2.display( ); //输出c2的值 cout<<″c1+c2=″; c3.display( ); //输出c3的值 return 0; } 例10.2 改写例10.1,重载运算符“+”,使之能用于两个复数相加。#include using namespace std; class Complex {public: Complex( ){real=0;imag=0;} Complex(double r,double i){real=r;imag=i;} Complex operator+(Complex &c2); //声明重载运算符的函数void display( ); private: double real; double imag; }; Complex Complex::operator+(Complex &c2) //定义重载运算符的函数

C++运算符重载

一、运算符重载的规则 运算符重载规则如下: ①、C++中的运算符除了少数几个之外,全部可以重载,而且只能重载C++中已有的运算符。 ②、重载之后运算符的优先级和结合性都不会改变。 ③、运算符重载是针对新类型数据的实际需要,对原有运算符进行适当的改造。一般来说,重载的功能应当与原有功能相类似,不能改变原运算符的操作对象个数,同时至少要有一个操作对象是自定义类型。 不能重载的运算符只有五个,它们是:成员运算符“.”、指针运算符“*”、作用域运算符“::”、“sizeof”、条件运算符“?:”。 运算符重载形式有两种,重载为类的成员函数和重载为类的友元函数。 运算符重载为类的成员函数的一般语法形式为: 函数类型 operator 运算符(形参表) { 函数体; } 运算符重载为类的友元函数的一般语法形式为: friend 函数类型 operator 运算符(形参表) { 函数体; } 其中,函数类型就是运算结果类型;operator是定义运算符重载函数的关键字;运算符是重载的运算符名称。 当运算符重载为类的成员函数时,函数的参数个数比原来的操作个数要少一个;当重载为类的友元函数时,参数个数与原操作数个数相同。原因是重载为类的成员函数时,如果某个对象使用重载了的成员函数,自身的数据可以直接访问,就不需要再放在参数表中进行传递,少了的操作数就是该对象本身。而重载为友元函数时,友元函数对某个对象的数据进行操作,就必须通过该对象的名称来进行,因此使用到的参数都要进行传递,操作数的个数就不会有变化。 运算符重载的主要优点就是允许改变使用于系统内部的运算符的操作方式,以适应用户自定义类型的类似运算。 一般说来,单目运算符最好被重载为成员;对双目运算符最好被重载为友元函数,双目运算符重载为友元函数比重载为成员函数更方便此,但是,有的双目运算符还是重载为成员函数为好,例如,赋值运算符。 二、运算符重载为成员函数 对于双目运算符B,如果要重载B为类的成员函数,使之能够实现表达式oprd1 B oprd2,其中oprd1为类A的对象,则应当把B重载为A类的成员函数,该函数只有一个形参,形参的类型是oprd2所属的类型。经过重载后,表达式oprd1 B oprd2 就相当于函数调用 oprd1.operator B(oprd2).

c++运算符重载习题

Task8-1 /* 1. 定义一个复数类Complex,重载运算符“+”,使之能用于复数的加法运算。将运算符函数重载为非成员、非友元的普通函数。编写程序,求两个复数之和*/ #include using namespace std; class Complex { public: Complex(){real=0;imag=0;} Complex(double r,double i){real=r;imag=i;} void display(); double real; double imag; }; void Complex::display() { cout<<"("<int) //这里编译器不会把2向上转换即(int->double) 这的强者类型转换 //呵呵恐怖吗你以为你在调用第二个函数结果调用的是第一个 system("pause"); }

C中用运算符重载实现矩阵运算

走进3D的世界 -- C++中用运算符重载实现矩阵运算 作者:周军 矩阵(Matrix)无处不在,我们的生活中到处都能找到矩阵的身影,然而此处我不想把这个定义放大,我们只讨论线性代数中的矩阵,我们要用它们来完成我们的3D变换。为什么矩阵可以完成3D变换呢?下面,我们就来介绍矩阵是如何变换坐标的: 设空间中有一坐标(x,y,z),如果我们想把它变换成另一坐标(x,’y’,z’),我们可以进行如下操作: = (x’,y’,z’,1) 这就是矩阵的妙用了。它在复杂处理变换的时候表现得尤为突出。假设我们想要把一个物体先沿z轴旋转角thetaZ,再沿x轴旋转角thetaX,我们可以进行如下操作(pseudo-code): obj*=rotX(thetaX)*rotZ(thetaZ); 注意:矩阵的乘法是不可逆的,而且我们要按变化顺序的逆序进行乘法,具体推导见计算几何相关书籍。 下面,我们进入正题:如何再C++中用重载运算符的方法来进行矩阵运算以完成线性变换呢?我们需要变换坐标,所以很自然地,我们需要一个向量(Vector)类;同时我们要进行

为直观、人性化,我选用了运算符重载这以技巧而不是简单地调用函数,下面请看我的具体实现:

以上便是CVector类的具体实现,我想对C++和线性代数有所了解的读者都能很清楚地理解这段代码,在次不累述。 上述代码的成员函数实在类外定义的,如果读者在实践中为了提高速度可以把这些成员函数定义在类内以起到内联函数的作用,可以省去参数压栈、出栈时的时间。 下面是CMatrix类的具体实现:

是不是也很好理解呢?哈哈,这就是用运算符重载的好处。不过这种方法也确实有它的不足,而且这个不足在游戏编程中是致命的,那就是效率不高,这也正是为什么Microsoft 在DirectX中也使用难看的一般函数调用来完成矩阵运算的原因。影响速度的主要原因是在使用运算符+、-、*、/等时,程序会在每次运算时创建临时对象再将临时对象返回,对于重复多次的矩阵运算来说,这无疑成为了一笔庞大的额外开销(好在现在的计算机的处理速度还算快)。但注意:在使用+=、-=、*=、/=时不会有上述问题,因为在使用这些运算符时程序只需要修改第一个对象不需要创建并返回临时对象。所以在能使用+=、-=、*=、/=时尽量不要使用单一的=、-、*、/运算符。 好了,这两个类我们已经封装好了,下面还有什么呢?是的,忘了向大家交代旋转矩阵了:

4运算符重载复习题2

运算符重载复习题2 1、下列运算符中, ()运算符在C++中不能重载。 A = B () C :: D delete 2、下列运算符中, ()运算符在C++中不能重载。 A ?: B [] C new D && 3、下列关于C++运算符函数的返回类型的描述中,错误的是()。 A 可以是类类型 B 可以是int类型 C 可以是void类型 D 可以是float类型 4、下列运算符不能用友元函数重载的是()。 A + B = C * D << 5、在重载运算符函数时,下面()运算符必须重载为类成员函数形式。 A + B - C ++ D -> 6、下列关于运算符重载的描述中,正确的是()。 A 运算符重载可以改变运算符的操作数的个数 B 运算符重载可以改变优先级 C 运算符重载可以改变结合性 D 运算符重载不可以改变语法结构 7、友元运算符obj>obj2被C++编译器解释为()。 A operator>(obj1,obj2) B >(obj1,obj2) C obj2.operator>(obj1) D obj1.oprator>(obj2) 8、在表达式x+y*z中,+是作为成员函数重载的运算符,*是作为非成员函数重载的运算符。下列叙述中正确的是()。 A operator+有两个参数,operator*有两个参数 B operator+有两个参数,operator*有一个参数 C operator+有一个参数,operator*有两个参数 D operator+有一个参数,operator*有一个参数 9、重载赋值操作符时,应声明为()函数。 A 友元 B 虚 C 成员 D 多态 10、在一个类中可以对一个操作符进行()重载。

c++运算符重载和多态性实验报告

实验5 运算符重载和多态性班级学号(最后两位)姓名成绩 一、实验目的 1.掌握用成员函数重载运算符的方法 2.掌握用友元函数重载运算符的方法 3.理解并掌握利用虚函数实现动态多态性和编写通用程序的方法 4.掌握纯虚函数和抽象类的使用 二、实验内容 1.复数类加减法乘除运算(用成员函数定义运算符重载)。 复数类的定义: class complex //复数类声明 { public: //外部接口 complex(double r=0.0,double i=0.0) //构造函数 {real=r,imag=i;} complex operator +(complex c2); //运算符"+"重载成员函数 complex operator - (complex c2); //运算符"-"重载成员函数 complex operator *(complex ); //运算符"*"重载成员函数 complex operator /(complex); //运算符"/"重载成员函数 complex operator =(complex c2); //运算符"="重载成员函数 void display(); //输出复数 private: //私有数据成员 double real; //复数实部 double imag; //复数虚部 }; 实验代码: #include using namespace std; class Complex { public: Complex() { real=0; imag=0; } Complex(double r,double i) { real=r; imag=i; } Complex operator+(Complex &c2); Complex operator-(Complex &c2); Complex operator*(Complex &c2); Complex operator/(Complex &c2); void display(); private: double real; double imag; };

C++重载运算符的几类使用方法

1.非运算符重载实现复数的加法运算//非运算符重载实现复数的加法运算 //complex.h #include #ifndef COMPLEX_H #define COMPLEX_H class complex { public: complex(); doublegetreal(); doublegetimag(); voidsetreal(double); voidsetimag(double); void display(); private: double real; double image; }; #endif //complex.cpp #include #include"complex.h" complex::complex() { real = 0; image = 0; } void complex::setreal(double r) { real = r; } void complex::setimag(double i) { image = i; } double complex::getreal() { return real; }

double complex::getimag() { return image; } void complex::display() { cout<<"the result is\n"< #include"complex.h" complex add(complex comp1,complex comp2); complex sub(complex comp1,complex comp2); void main() { complex c1,c2,c3,c4; c1.setreal(2.0); c1.setimag(3.0); c2.setreal(1.0); c2.setimag(4.0); c3 = add(c1,c2); cout<<"c3 = c1 + c2 , "; c3.display(); c4 = sub(c1,c2); cout<<"c4 = c1 - c2 ,"; c4.display(); } complex add(complex comp1,complex comp2) { complex temp; temp.setreal(comp1.getreal() + comp2.getreal()); temp.setimag(comp1.getimag() + comp2.getimag()); return temp; } complex sub(complex comp1,complex comp2) { complex temp; temp.setreal(comp1.getreal() - comp2.getreal()); temp.setimag(comp1.getimag() - comp2.getimag()); return temp; } 2.运算符重载作为类的成员函数 //运算符重载作为类的成员函数

运算符重载综合实例

运算符重载综合实例 class MyComplex{ double Real;double Imag; public: //构造函数 MyComplex(const double &r=0.0,const double &i=0.0){Real=r;Imag=i;cout<<"Constructor !"<

运算符重载基础概念练习题

运算符重载基础概念练习题 1、下列运算符中, ()运算符在C++中不能重载。 A = B () C :: D delete 2、下列运算符中, ()运算符在C++中不能重载。 A ?: B [] C new D && 3、下列关于C++运算符函数的返回类型的描述中,错误的是()。 A 可以是类类型 B 可以是int类型 C 可以是void类型 D 可以是float类型 4、下列运算符不能用友元函数重载的是()。 A + B = C * D << 5、在重载运算符函数时,下面()运算符必须重载为类成员函数形式。 A + B - C ++ D -> 6、下列关于运算符重载的描述中,正确的是()。 A 运算符重载可以改变运算符的操作数的个数 B 运算符重载可以改变优先级 C 运算符重载可以改变结合性 D 运算符重载不可以改变语法结构 7、友元运算符obj>obj2被C++编译器解释为()。 A operator>(obj1,obj2) B >(obj1,obj2) C obj2.operator>(obj1) D obj1.oprator>(obj2) 8、在表达式x+y*z中,+是作为成员函数重载的运算符,*是作为非成员函数重载的运算符。下列叙述中正确的是()。 A operator+有两个参数,operator*有两个参数 B operator+有两个参数,operator*有一个参数 C operator+有一个参数,operator*有两个参数 D operator+有一个参数,operator*有一个参数 9、重载赋值操作符时,应声明为()函数。 A 友元 B 虚 C 成员 D 多态 10、在一个类中可以对一个操作符进行()重载。 A 1种 B 2种以下 C 3种以下 D 多种 11、在重载一个运算符时,其参数表中没有任何参数,这表明该运算符是()。

operator运算符重载

8.4 运算符重载 运算符重载是非常重要的功能,因为它使我们能够使用像+、–、*这样的标准C++运算符,来处理自定义数据类型的对象。该功能允许我们编写重新定义特定运算符的函数,从而使该运算符处理类对象时执行特定的动作。例如,我们可以重新定义>运算符,从而使该运算符用于前面看到的CBox类对象时,如果第一个实参的体积比第二个大,就返回true。 运算符重载功能不允许我们使用新的运算符,也不允许我们改变运算符的优先级,因此运算符的重载版本在计算表达式的值时优先级与原来的基本运算符相同。运算符的优先级表可以在本书第2章和MSDN库中找到。 虽然我们不能重载所有运算符,但限制不是特别严格。下面给出不能重载的运算符: 作用域解析运算符 :: 条件运算符 ?: 直接成员访问运算符 . sizeof运算符 sizeof 解除对指向类成员的指针的引用运算符 .* 任何其他运算符都是可以重载的,这给予我们相当大的灵活性。显然,确保标准运算符的重载版本与原来的正常用途一致,或者至少在操作上相当直观,是合适的想法。如果为某个类重载的+运算符却执行使类对象相乘的操作,这可能就不是明智的做法。理解运算符重载机制如何工作的最好方法是完成一个示例,因此下面为CBox类实现刚才提到的大于运算符>。 8.4.1 实现重载的运算符 为了给某个类实现重载的运算符,我们必须编写特殊的函数。假设在类定义内重载>运算符的函数是CBox类的成员,则该函数的声明如下所示: class CBox { public:

bool operator>(CBox& aBox) const; // Overloaded 'greater than' // Rest of the class definition... }; 这里的单词operator是个关键字。该关键字结合运算符符号或名称,本例中是>,将定义一个运算符函数。本例中的函数名是operator>()。在运算符函数的声明中,关键字和运算符本身之间有无空格都行,前提是没有歧义。歧义出现在运算符是名称而非符号的时候,比如new或delete。如果写成不加空格的operatornew和operatordelete,则它们都是合法的普通函数名。因此,如果要编写这些运算符的运算符函数,则必须在关键字operator和运算符名称之间加个空格。注意,我们将函数声明为const,因为该函数不修改本类的数据成员。 在operator>()运算符函数中,运算符的右操作数由函数形参定义,左操作数由this指针隐式定义。因此,如果有下面这条if语句: if(box1 > box2) cout << endl << "box1 is greater than box2"; 则括弧中的表达式将调用重载的运算符函数,它与下面这个函数调用等价: box1.operator>(box2); 表达式中的CBox对象与运算符函数形参之间的对应关系如图8-3所示。 图8-3 下面介绍operator>()函数的工作原理: // Operator function for 'greater than' which // compares volumes of CBox objects. bool CBox::operator>(const CBox& aBox) const { return this->Volume() > aBox.V olume(); }

实验10 运算符重载(2) (1)

实验10 运算符重载(2) 一、实验目的 进一步理解运算符重载,运用成员函数和友元函数等方法实现运算符的重载。 二、实验内容 1、用友元函数重载运算符,使对整型的运算符=、+、-、*、/ 适用于分数运算。 2、重载下标运算符使之返回集合中最大的元素、次最大的元素以及第三大的元素。 3、定义一个人民币类RMB,包含私有数据成员元、角、分,请用友元函数重载运算符“+”和“++”,以对类对象进行运算。 4.设计一个日期类Date,,要求: (1)包含年(year)、月(month)和日(day)私有数据成员。 (2)包含构造函数,重载关于一日期加上天数的加法运算符+、重载关于一日期减去天数的减加运算符-、重载输出运算符<<与输入运算符>>等。 提示:由于各C++编译器对于重载输入/出运算符为友元的兼容性都存在问题,最好重载输入/出运算符不声明为成员函数与友元函数,而声明一般函数,为编程更方便,可增加一些成员函数,比如: void SetYear(int y); // 设置年 int SetMonth(int m); // 设置月 int SetDay(int d); // 设置日 int GetYear() const; // 返回年 int GetMonth() const; // 返回月 int GetDay() const; // 返回日 static int IsLeapyear(int y); // 判断年份y是否为润年 static int GetDays(int y); // 年份y的天数 static int GetDays(const Date &d); // 日期d当前月份的天数 static int DateToNum(const Date &d); // 返回从公元1年1月1日起的天数 static Date NumToDate(int n); //由从公元1年1月1日起的天数返回日期 润年条件:年份能被4整除,并且年份不能被100整除,或者年份能被400整除 润年天数:366 平年天数:365 润年2月份天数:29 平年2月份天数:28 5.设计一个时间类Time,要求: (1)包含时(hour)、分(minute)和秒(second)私有数据成员。 (2)包含构造函数,重载关于一时间加上另一时间的加法运算符+、重载关于一时间减去另一时间的减加运算符-、重载输出运算符<<与输入运算符>>等。 提示:可仿照第4题编程实现,可将时间转换成秒数,将秒数转成时间进行辅助编程。 时间转换成秒数: 秒数= 时* 3600 + 分* 60 + 秒

c 运算符重载总结

c++运算符重载总结 目录1.一般运算符重载2.关系运算符重载3.逻辑运算符重载4.单目运算符重载5.自增减运算符重载6.位运算符重载7.赋值运算符重载8.内存运算符重载9.特殊运算符重载10.总结c++的一大特性就是重载(overload),通过重载可以把功能相似的几个函数合为一个,使得程序更加简洁、高效。在c++中不止函数可以重载,运算符也可以重载。由于一般数据类型间的运算符没有重载的必要,所以运算符重载主要是面向对象之间的。 1.一般运算符重载 在进行对象之间的运算时,程序会调用与运算符相对应的函数进行处理,所以运算符重载有两种方式:成员函数和友元函数。成员函数的形式比较简单,就是在类里面定义了一个与操作符相关的函数。友元函数因为没有this指针,所以形参会多一个。 class A{public: A(int d):data(d){} A operator+(A&);//成员函数A operator-(A&); A operator*(A&); A operator/(A&); A operator%(A&); friend A operator+(A&,A&);//友元函数friend A operator-(A&,A&); friend A operator*(A&,A&); friend A operator/(A&,A&); friend A operator%(A&,A&);private: int data;};//成员函数的形式A A::operator+(A &a){ return

A(data+a.data);}A A::operator-(A &a){ return A(data-a.data);}A A::operator*(A &a){ return A(data*a.data);}A A::operator/(A &a){ return A(data/a.data);}A A::operator%(A &a){ return A(data%a.data);}//友元函数的形式A operator+(A &a1,A &a2){ return A(a1.data+a2.data);}A operator-(A &a1,A &a2){ return A(a1.data-a2.data);}A operator*(A &a1,A &a2){ return A(a1.data*a2.data);}A operator/(A &a1,A &a2){ return A(a1.data/a2.data);}A operator%(A &a1,A &a2){ return A(a1.data%a2.data);}//然后我们就可以对类的对象进行+、-、*、/了。void main(void){ A a1(1),a2(2),a3(3); a1=a2+a3; //或者a1=a2.operator+(a3);} 注意:在进行a2+a3的时候会出错,因为我们在上面对+定义了两种方法,去掉一种即可。 2.关系运算符重载 因为函数体比较简单,后面我就只给出成员函数形式的函数声明了,关系运算符有==,!=,,=。 bool operator == (const A& ); bool operator != (const A& );bool operator bool operator bool operator > (const A& );bool operator >= (const A& ); 3.逻辑运算符重载 bool operator || (const A& );bool operator && (const A& );bool operator ! ();

相关主题
文本预览
相关文档 最新文档