1 / 25

第 7 章 运算符重载

第 7 章 运算符重载. 7.1 运算符重载概述. 7.1.1 运算符重载的好处. 定义一个简化的复数类 complex: class complex { public: double real,imag; complex(double r=0,double i=0) { real=r; imag=i;} }; 若要把类 complex 的两个对象 com1 和 com2 加在一起 , 下面的语句是不能实现的 : main() {

tana
Download Presentation

第 7 章 运算符重载

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第7章 运算符重载

  2. 7.1运算符重载概述 7.1.1 运算符重载的好处

  3. 定义一个简化的复数类complex: class complex { public: double real,imag; complex(double r=0,double i=0) { real=r; imag=i;} }; 若要把类complex的两个对象com1和com2加在一起,下面的语句是不能实现的: main() { complex com1(1.1,2.2),com2(3.3,4.4),total; total=com1+com2; //错误 //… return 0; }

  4. 若要将上述类complex的两个对象相加,只要编写一个运算符函数operator+(),如下所示:若要将上述类complex的两个对象相加,只要编写一个运算符函数operator+(),如下所示: complex operator+(complex om1,complex om2) { complex temp; temp.real=om1.real+om2.real; temp.imag=om1.imag+om2.imag; return temp; } 我们就能方便地使用语句: total=com1+com2; 将类complex的两个对象com1和com2相加。

  5. 7.2 运算符重载函数的两种形式 7.2.1 友元运算符函数 在C++中,可以把运算符重载函数定义成某个类的友元函数,称为友元运算符函数。

  6. 1. 友元运算符函数定义的语法形式 友元运算符函数的原型在类的内部声明格式如下: class X { //… friend 返回类型 operator运算符(形参表); //… } 在类外定义友元运算符函数的格式如下: 返回类型 operator运算符(形参表) { 函数体 }

  7. 2. 双目运算符重载 当用友元函数重载双目运算符时,两个操作数都要传递给运算符函数。 例7.2 用友元运算符函数进行复数运算。

  8. 一般而言,如果在类X中采用友元函数重载双目运算符@,而aa和bb是类X的两个对象,则以下两种函数调用方法是等价的:一般而言,如果在类X中采用友元函数重载双目运算符@,而aa和bb是类X的两个对象,则以下两种函数调用方法是等价的: aa @ bb; // 隐式调用 operator @(aa,bb); // 显式调用

  9. 3. 单目运算符重载 用友元函数重载单目运算符时,需要一个显式的操作数。 例7.3 用友元函数重载单目运算符“-”。

  10. 一般而言,如果在类X中采用友元函数重载单目运算符@,而aa是类X的对象,则以下两种函数调用方法是等价的:一般而言,如果在类X中采用友元函数重载单目运算符@,而aa是类X的对象,则以下两种函数调用方法是等价的: @aa; // 隐式调用 operator@(aa); // 显式调用

  11. 7.2.2 成员运算符函数 在C++中,可以把运算符函数定义成某个类的成员函数,称为成员运算符函数。

  12. 1.成员运算符函数定义的语法形式 成员运算符函数的原型在类的内部声明格式如下: class X { //… 返回类型 operator运算符(形参表); //… } 在类外定义成员运算符函数的格式如下: 返回类型 X::operator运算符(形参表) { 函数体 }

  13. 2. 双目运算符重载 对双目运算符而言,成员运算符函数的形参表中仅有一个参数,它作为运算符的右操作数,此时当前对象作为运算符的左操作数,它是通过this指针隐含地传递给函数的。 例7.6 采用成员运算符函数来完成例7.2中同样的工作。

  14. 一般而言,如果在类X中采用成员函数重载双目运算符@,成员运算符函数operator@ 所需的一个操作数由对象aa通过this指针隐含地传递,它的另一个操作数bb在参数表中显示,aa和bb是类X的两个对象,则以下两种函数调用方法是等价的: aa @ bb; // 隐式调用 aa.operator @(bb); // 显式调用

  15. 3. 单目运算符重载 对单目运算符而言,成员运算符函数的参数表中没有参数,此时当前对象作为运算符的一个操作数。 。 例7.7 重载单目运算符“++”。

  16. 一般而言,采用成员函数重载单目运算符时,以下两种方法是等价的:一般而言,采用成员函数重载单目运算符时,以下两种方法是等价的: @aa; // 隐式调用 aa.operator@(); // 显式调用 成员运算符函数operator @所需的一个操作数由对象aa通过this指针隐含地传递。因此,在它的参数表中没有参数。

  17. 7.2.3 成员运算符函数与友元运算符函数的比较 (1) 对双目运算符而言,成员运算符函数带有一个参数,而友元运算符函数带有两个参数;对单目运算符而言,成员运算符函数不带参数,而友元运算符函数带一个参数。 (2) 双目运算符一般可以被重载为友元运算符函数或成员运算符函数,但有一种情况,必须使用友元函数。 (3) 成员运算符函数和友元运算符函数可以用习惯方式调用,也可以用它们专用的方式调用,表7-1列出了一般情况下运算符函数的调用形式。 (4) C++的大部分运算符既可说明为成员运算符函数,又可说明为友元运算符函数。究竟选择哪一种运算符好一些,没有定论,这主要取决于实际情况和程序员的习惯。

  18. 7.3 几个常用运算符的重载 7.3.1 单目运算符“++”和“--”的重载 在C++中,可以通过在运算符函数参数表中是否插入关键字int来区分前缀和后缀这两种方式。 ◆对于前缀方式++ob,可以用运算符函数重载为 ob.operator ++(); // 成员函数重载 或 operator ++ (X& ob); // 友元函数重载, 其中ob为类X对象的引用 ◆ 对于后缀方式ob++,可以用运算符函数重载为 ob.ooperator ++(int); // 成员函数重载 或 operator++(X& ob,int); // 友元函数重载 在调用后缀方式的函数时,参数int一般被传递给值0。

  19. 7.3.2 赋值运算符“=”的重载 对任一类X,如果没有用户自定义的赋值运算符函数,那么系统自动地为其生成一个缺省的赋值运算符函数,定义为类X中的成员到成员的赋值,例如: X &X::operator=(const X& source) { //…成员间赋值 } 若obj1和obj2是类X的两个对象,obj2已被创建,则编译程序遇到如下语句: obj1=obj2; 就调用缺省的赋值运算符函数,将对象obj2的数据成员的值逐个赋给对象obj1的对应数据成员中。

  20. 1.指针悬挂问题 在某些特殊情况下,如类中有指针类型时,使用缺省的赋值运算符函数会产生错误。

  21. 例7.11 使用缺省的赋值运算符函数产生错误的例子。 #include <iostream.h> #include<string.h> class string { public: string(char *s) { ptr=new char[strlen(s)+1]; strcpy(ptr,s); } ~string() { delete ptr; } void print() { cout<<ptr<<endl; } private: char *ptr; };

  22. void main() { string p1("book"); string p2("pen"); p1=p2; cout<<"p2:"; p2.print(); cout<<"p1:"; p1.print(); }

  23. 2. 重载赋值运算符解决指针悬挂问题 为了解决上述使用缺省的赋值运算符所遇到的指针悬挂问题,必须重载赋值运算符,使得对目标对象数据成员指针的赋值,是把原对象指针ptr所指向的内容传递给它,而不是简单地传递指针值。

  24. 例7.12 重载赋值运算符解决指针悬挂问题。 #include <iostream.h> #include<string.h> class string { public: string(char *s) { ptr=new char[strlen(s)+1]; strcpy(ptr,s);} ~string(){ delete ptr; } void print(){ cout<<ptr<<endl; } string& operator=(const string&);//声明赋值运算符重载函数 private: char *ptr; };

  25. string& string::operator=(const string& s) // 定义赋值运算符 重载函数 { if (this==&s) return *this; // 防止s=s的赋值 delete ptr; // 释放掉原区域 ptr=new char[strlen(s.ptr)+1]; // 分配新区域 strcpy(ptr,s.ptr); // 字符串拷贝 return *this; } void main() { string p1("book"); string p2("pen"); p1=p2; cout<<"p2:"; p2.print(); cout<<"p1:"; p1.print(); }

More Related