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

运算符重载

运算符重载
运算符重载

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.Volume();

}

该函数使用引用形参,以避免被调用时不必要的复制开销。因为该函数不需要修改调用它的对象,所以可将其声明为const。如果不这样做,我们将根本不能使用该运算符比较CBox 类型的const对象。

return表达式使用成员函数Volume()计算this指向的CBox对象的体积,然后使用基本运算符>,将结果与对象aBox的体积进行比较。基本运算符>返回int(而非bool)类型的数值,因此如果指针this指向的对象比作为引用实参传递的对象aBox的体积大,则返回1,否则返回0。比较结果将自动转换为该运算符函数的返回类型bool。

试一试:运算符重载

我们可以通过如下示例练习如何使用operator>()函数。

// Ex8_03.cpp

// Exercising the overloaded 'greater than' operator

#include // For stream I/O

using std::cout;

using std::endl;

class CBox // Class definition at global scope {

public:

// Constructor definition

CBox(double lv = 1.0, double wv = 1.0, double hv = 1.0):

m_Length(lv), m_Width(wv), m_Height(hv) {

cout << endl << "Constructor called.";

}

// Function to calculate the volume of a box

double Volume() const

{

return m_Length*m_Width*m_Height;

bool operator>(const CBox& aBox) const; // Overloaded 'greater than' // Destructor definition

~CBox()

{

cout << "Destructor called." << endl;

}

private:

double m_Length; // Length of a box in inches

double m_Width; // Width of a box in inches

double m_Height; // Height of a box in inches

};

// Operator function for 'greater than' that

// compares volumes of CBox objects.

bool CBox::operator>(const CBox& aBox) const

{

return this->Volume() > aBox.Volume();

int main()

{

CBox smallBox(4.0, 2.0, 1.0);

CBox mediumBox(10.0, 4.0, 2.0);

CBox bigBox(30.0, 20.0, 40.0);

if(mediumBox > smallBox)

cout << endl

<< "mediumBox is bigger than smallBox"; if(mediumBox > bigBox)

cout << endl

<< "mediumBox is bigger than bigBox";

else

cout << endl

<< "mediumBox is not bigger than bigBox"; cout << endl;

return 0;

示例说明

operator>()运算符函数的原型出现在类的public部分。由于函数定义在类定义外部,因此该函数默认不是内联函数。这样安排是非常随意的。我们完全可以将函数定义放在类定义中原型的位置,这种情况下将不需要在函数名前面用CBox::加以限定。我们记得,当某个函数成员在类定义外部定义时,为了告诉编译器该函数是CBox类的成员,必须用类名进行限定。

main()函数中有两条对类成员使用>运算符的if语句,它们将自动调用我们实现的重载运算符。如果想确认这一点,那么可以给运算符函数添加一条输出语句。该示例的输出如下:

Constructor called.

Constructor called.

Constructor called.

mediumBox is bigger than smallBox

mediumBox is not bigger than bigBox

Destructor called.

Destructor called.

Destructor called.

输出证实,使用运算符函数的if语句工作正常,因此直接用CBox对象表示CBox问题的解决方案开始成为很现实的命题。

8.4.2 实现对运算符的完全支持

使用前面实现的operator>()运算符函数,我们仍然有许多事情不能做。用CBox对象指定问题的解决方案完全可能涉及像下面这样的语句:

if(aBox > 20.0)

// Do something...

我们的函数不会处理这里的表达式。如果试图使用比较CBox对象与数值的表达式,那么将得到一条出错消息。为了支持该功能,需要编写另一个版本的operator>()函数作为重载函数。

要支持刚刚看到的表达式类型非常容易。类定义内的成员函数声明将如下所示:

// Compare a CBox object with a constant

bool operator>(const double& value) const;

该语句应出现在类定义中,>运算符的右操作数对应于这里的函数形参。作为左操作数的CBox对象是由隐式指针this传递的。

该重载运算符的实现同样很容易,函数体内只有一条语句:

// Function to compare a CBox object with a constant

bool CBox::operator>(const double& value) const

{

return this->Volume() > value;

}

没有比这更简单的事情了,不是吗?但使用>运算符处理CBox对象仍然存在问题。我们有可能希望写出下面这样的语句:

if(20.0 > aBox)

// do something...

有人可能争辩说,通过实现接受double类型右实参的operator<()运算符函数,然后相应改写上面这条语句,同样可以完成相同的功能,这么说非常正确。实际上无论如何,实现<运算符都可能是比较CBox对象所必需的。但是,在实现对某种对象类型的支持时,我们不应该人为限制在表达式中使用这种对象的方式。对象的使用应该尽可能自然。现在的问题是如何来做。

成员运算符函数总是以左边的实参作为指针this。因为本例中左边的实参是double类型,所以我们不能以成员函数的形式实现该运算符。剩下的只有两种选择:普通函数或友元函数。我们不需要访问CBox类的private成员,所以该函数不必是友元函数。因此,我们可以将左操作数属于double类型的重载>运算符实现为普通函数。由于该函数不是成员函数,其原型当然应该放在类定义的外部:

bool operator>(const double& value, const CBox& aBox);

该函数的实现如下:

// Function comparing a constant with a CBox object

bool operator>(const double& value, const CBox& aBox)

{

return value > aBox.Volume();

}

正如前面曾经看到的那样,普通函数(就这一点而论也包括友元函数)使用直接成员选择运算符和对象名访问对象的成员。当然,普通函数只能访问公有成员。成员函数Volume()是公有的,因此这里使用该函数没有什么问题。

如果CBox类没有公有函数Volume(),我们可以直接使用能够访问私有数据成员的友元函

数,或者提供一组返回私有数据成员数值的成员函数,然后在普通函数中使用这些函数来实现比较功能。

试一试:完成>运算符的重载

我们可以在示例中将所有这些放在一起,以说明实际的工作过程:

// Ex8_04.cpp

// Implementing a complete overloaded 'greater than' operator

#include // For stream I/O

using std::cout;

using std::endl;

class CBox // Class definition at global scope

{

public:

// Constructor definition

CBox(double lv = 1.0, double wv = 1.0, double hv = 1.0):

m_Length(lv), m_Width(wv), m_Height(hv)

{

cout << endl << "Constructor called.";

}

// Function to calculate the volume of a box

double Volume() const

{

return m_Length*m_Width*m_Height;

}

// Operator function for 'greater than' that

// compares volumes of CBox objects.

bool operator>(const CBox& aBox) const

{

return this->Volume() > aBox.Volume();

}

// Function to compare a CBox object with a constant bool operator>(const double& value) const

{

return this->Volume() > value;

}

// Destructor definition

~CBox()

{ cout << "Destructor called." << endl;}

private:

double m_Length; // Length of a box in inches

double m_Width; // Width of a box in inches

double m_Height; // Height of a box in inches

};

int operator>(const double& value, const CBox& aBox); // Function prototype int main()

{

CBox smallBox(4.0, 2.0, 1.0);

CBox mediumBox(10.0, 4.0, 2.0);

if(mediumBox > smallBox)

cout << endl

<< "mediumBox is bigger than smallBox";

if(mediumBox > 50.0)

cout << endl

<< "mediumBox capacity is more than 50";

else

cout << endl

<< "mediumBox capacity is not more than 50";

if(10.0 > smallBox)

cout << endl

<< "smallBox capacity is less than 10";

else

cout << endl

<< "smallBox capacity is not less than 10";

cout << endl;

return 0;

}

// Function comparing a constant with a CBox object int operator>(const double& value, const CBox& aBox) {

return value > aBox.Volume();

}

示例说明

注意普通版本operator>()函数的原型所处的位置。该原型需要跟在类定义后面,因为其形参列表中要引用CBox对象。如果我们将其放在类定义前面,则该示例将不能编译。

有一种将其放在程序文件开头#include语句后面的方法:使用未完成的类声明。这样该函数的原型就可以放在类定义之前,声明语句如下所示:

class CBox; // Incomplete class declaration

int operator>(const double& value, CBox& aBox); // Function prototype

未完成的类声明告诉编译器CBox是一个类,这足以使编译器正确处理第二行的函数原型,因为它现在知道CBox是后面将要定义的用户定义类型。

如果有两个类,而每个类都有一个指针成员指向另一个类的对象,在此类情形中我们同样需要上述机制。这两个类都要求另一个类首先被声明,通过使用未完成的类声明就可以打破这样的僵局。

该示例的输出如下:

Constructor called.

Constructor called.

mediumBox is bigger than smallBox

mediumBox capacity is more than 50

smallBox capacity is less than 10

Destructor called.

Destructor called.

在构造函数因对象smallBox和mediumBox的声明而输出消息之后,我们从3条if语句中得到3行输出,每条语句都像我们预期的那样工作。其中第一条语句调用属于类成员的运算符函数,比较CBox类的两个对象。第二条语句调用形参类型为double的成员函数。第三条if语句中的表达式调用以普通函数形式实现的运算符函数。

碰巧的是,两个属于类成员的运算符函数亦可以普通函数的形式实现,因为它们只需要访问公有成员函数Volume()。

注意:

以完全相同的实现大于运算符的方法,我们可以实现任何比较运算符。它们仅仅在次要细节方面不同,大体的实现方法则完全相同。

运算符重载练习题.

运算符重载 一.单项选择题 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/b98306698.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 ! ();

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