第7章 运算符重载
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
– C++语言提供的标准运算符可以重新在类中 定义,使标准运算符作用于类的对象,从而 使对象的计算操作表示得既自然又符合常规。
• 运算符函数
– C++将运算符看作一种特殊类型的函数,运 算符的重载是通过对运算符函数的重载实现 的。运算符函数名由关键字operator 和重载 得运算符组成。
运算符重载的方法
这种表示复数加法 很不直观
运算符函数
class complex{ / / very simplified complex double re, im; public: complex(double r, double i) : re(r) , im(i) { } complex operator+(complex) ; complex operator*(complex) ; 运算符 }; 函数
时钟类例子(续4)
//其它成员函数的实现略 void main( ) { Clock myClock(23,59,59); cout<<"First time output:"; myClock.ShowTime(); myClock++; myClock.ShowTime(); ++myClock; myClock.ShowTime(); }
7.1 重载运算符的目的
• • • • 简略的表达方法 函数式的表达方法 运算符函数 运算符重载
简略的表达方法
x+y*z
简略的表达方法是一种缩略或公式化表达 的方法。
好处:简明直观、能提高交流效率。
函数式的表达方法
class Complex{ private: double real; double image; public: Complex( ); Complex& Add(Complex&); }; //… Complex object1,object2,object3; …… object3 =object1.Add(object2);
简单复数类的运算符重载(续)
//重载运算符 - 函数实现 complex complex::operator - (complex c2) { complex c; c.real=real-c2.real; c.imag=imag-c2.imag; return complex(c.real,c.imag); }
– 1.它有一个引用参数,这防止了对赋值号右边对 象进行拷贝。(提高效率) – 2.函数返回了引用,而不是对象。 – 复制构造函数不如使用引用参数和返回引用有效, 简便。
counter类例子
单目运算符
friend complex operator++(complex);
friend complex operator+(complex,complex); 友元函数 //…
7.6 ―++‖和―--‖的重载
时钟类例子
• 运算符前置++和后置++重载为时钟类的 成员函数 • 操作数是时钟类的对象 • 前置单目运算符,重载函数没有形参 • 对于后置单目运算符,重载函数需要有 一个整型形参。 • 实现时间增加1秒钟。
复数类的友元运算符函数
#include<iostream.h> class complex //复数类声明 { public: //外部接口 complex(double r=0.0,double i=0.0) { real=r; imag=i; } //构造函数 friend complex operator + (complex c1,complex c2); //运算符+重载为友元函数 friend complex operator - (complex c1,complex c2); //运算符-重载为友元函数 void display(); //显示复数的值 private: //私有数据成员 double real; double imag; };
7.5 成员运算符函数与友元运算符函数比较
C++的大部分运算符即可以说明为成员函数运算 符,也可以说明成友元函数运算符。 究竟选择哪一种运算符函数好一些,没有定论, 这主要取决于实际情况和程序员的习惯。 如果二元运算符的第一个操作数不是用户自定义 类型,则只能用友元的方式实现,而不能用成 员的方式实现。 下列运算符不能用友元函数来重载: = ( )[ ] -> 成员运算符函数的优点: 体现了面向对象的思想。
第7章
运算符重载
7.1 重载运算符的目的 7.2 运算符重载语法 7.3 成员运算符函数 7.4 友元运算符函数 7.5 成员运算符函数与友元运算符函数比较 7.6 ―++‖和“--‖的重载 7.7 赋值运算符“=‖的重载 7.7 下标运算符”[ ]‖与函数调用运算符”( )‖的重 载 7.9 构造函数用于类型转换 7.10 应用举例
成员和友元运算符函数
class complex{ double re,im; 双目运算符
public:
complex(double r, double I) { re=r; im=i; }
成员函数
complex( ) { re=im=0; } complex operator+(complex ); complex operator++( );
简单复数类的运算符重载(续)
程序输出的结果为: c1=(5,4) c2=(2,10) c3=c1-c2=(3,-6) c3=c1+c2=(7,14) 注:交换c1和c2的位置,不影响结果。
7.4 友元运算符函数
• 重载为友元函数时 参数个数=原操作数个数,且 至少应该有一个自定义类型的形参。 • 友元函数是类以外的函数,调用这种运算符函数时, 所有的操作数都要通过参数传递来获得。 如: class complex {public friend complex operator + (complex c1, complex c2); ……. }
复数类的友元运算符函数(续)
complex operator +(complex c1,complex c2) //运算符重载友元函数实现 { return complex(c2.real+c1.real, c2.imag+c1.imag);
}
complex operator -(complex c1,complex c2) //运算符重载友元函数实现 { return complex(c1.real-c2.real, c1.imag-c2.imag); } // 其它部分同上例
简单复数类的运算符重载(续)
//重载运算符函数的实现 complex complex::operator +(complex c2) { complex c; c.real=c2.real+real; c.imag=c2.imag+imag; return complex(c.real,c.imag); }
简单复数类的运算符重载(续)
void complex::display( ) { cout<<"("<<real<<","<<imag<<")"<<endl; } void main() //主函数 { complex c1(5,4),c2(2,10),c3; //定义复数类的对象 cout<<"c1="; c1.display(); cout<<"c2="; c2.display(); c3=c1-c2; //使用重载运算符完成复数减法 cout<<"c3=c1-c2="; c3.display(); c3=c1+c2; //使用重载运算符完成复数加法 cout<<"c3=c1+c2="; c3.display(); }
《C++面向对象程序设计》教学内容
第1章 C++概述 第2章 类和对象 第3章 面向对象程序设计概述 第4章 进一步学习类和对象 第5章 堆与复制构造函数 第6章 继承性:派生类 第7章 运算符重载 第8章 虚函数和多态性 第9章 模板 第10章 类库和C++的标准模板库STL 第11章 输入输出流 第12章 异常处理
运算符重载
void f( ) { complex a = complex(1, 3.1) ; complex b = complex(1.2, 2) ; complex c = b; a = b+c; b = b+c*a; c = a*b+complex(1,2) ; }
7.2 运算符重载语法
• 运算符重载
• 实现机制
– 运算符重载的实质就是函数重载:每个运 算符对应各自的运算符函数,根据操作数 的不同调用不同的同名函数。 – 将指定的运算表达式转化为对运算符函数 的调用,运算对象转化为运算符函数的实 参。
7.3 成员运算符函数
• 重载为类成员函数时 参数个数=原操作数个数-1 (后置++、--除外) • 当类的对象调用这种运算符函数时,对象中的成 员数据就可以是一个操作数,另一个操作数才通过 参数传递来获得。 • 如: class complex {public complex operator + (complex c2); ……. }
简单复数类的运算符重载
#include<iostream.h> class complex //复数类声明 { public: //外部接口 complex(double r=0.0,double i=0.0) {real=r;imag=i;} //构造函数 complex operator + (complex c2); //+重载为成员函数 complex operator - (complex c2); //-重为载成员函数 void display( ); //输出复数 private: //私有数据成员 double real; //复数实部 double imag; //复数虚部 };
时钟类例子(续1)
#include<iostream.h> class Clock //时钟类声明 { public: //外部接口 Clock(int NewH=0, int NewM=0, int NewS=0); void ShowTime(); void operator ++(); //前置单目运算符重载 void operator ++(int); //后置单目运算符重载 private: //私有数据成员 int Hour, Minute, Second; };
时钟类例子(续3)
void Clock::operator ++(int) //后置单目运算符重载 { Second++; if(Second>=60) { Second=Second-60; Minute++; if(Minute>=60) {Minute=Minute-60; Hour++; Hour=Hour%24; } } cout<<"Clock++: "; }
时钟类例子(续2)
void Clock::operator ++() //前置单目运算符重载函数 { Second++; if(Second>=60) { Second=Second-60; Minute++; if(Minute>=60) { Minute=Minute-60; Hour++; Hour=Hour%24; } } cout<<"++Clock: "; }
时钟类例子(续5)
程序运行结果为:
First time output:23:59:59 Clock++: 0:0:0 ++Clock: 0:0:1
7.7 赋值运算符―=‖的重载
• 如果没有为类显式地定义赋值运算符,编译器 将自动产生一个缺省的赋值运算符函数,它执 行以字节为单位的复制操作。 • 注意operator=()函数的两个重要特点:
• 首先在类定义时说明待重载的运算符,其格式为: 返回值类型 operator op (参数表);
ຫໍສະໝຸດ Baidu
• 然后象定义函数一样定义重载运算符函数。
返回值类型 类名称∷operator op(参数表)
{ //…… 运算符处理程序代码 }
运算符重载的实质
• 必要性
– C++中预定义的运算符其运算对象只能是 基本数据类型,而不适用于用户自定义类 型(如类)
• 运算符函数
– C++将运算符看作一种特殊类型的函数,运 算符的重载是通过对运算符函数的重载实现 的。运算符函数名由关键字operator 和重载 得运算符组成。
运算符重载的方法
这种表示复数加法 很不直观
运算符函数
class complex{ / / very simplified complex double re, im; public: complex(double r, double i) : re(r) , im(i) { } complex operator+(complex) ; complex operator*(complex) ; 运算符 }; 函数
时钟类例子(续4)
//其它成员函数的实现略 void main( ) { Clock myClock(23,59,59); cout<<"First time output:"; myClock.ShowTime(); myClock++; myClock.ShowTime(); ++myClock; myClock.ShowTime(); }
7.1 重载运算符的目的
• • • • 简略的表达方法 函数式的表达方法 运算符函数 运算符重载
简略的表达方法
x+y*z
简略的表达方法是一种缩略或公式化表达 的方法。
好处:简明直观、能提高交流效率。
函数式的表达方法
class Complex{ private: double real; double image; public: Complex( ); Complex& Add(Complex&); }; //… Complex object1,object2,object3; …… object3 =object1.Add(object2);
简单复数类的运算符重载(续)
//重载运算符 - 函数实现 complex complex::operator - (complex c2) { complex c; c.real=real-c2.real; c.imag=imag-c2.imag; return complex(c.real,c.imag); }
– 1.它有一个引用参数,这防止了对赋值号右边对 象进行拷贝。(提高效率) – 2.函数返回了引用,而不是对象。 – 复制构造函数不如使用引用参数和返回引用有效, 简便。
counter类例子
单目运算符
friend complex operator++(complex);
friend complex operator+(complex,complex); 友元函数 //…
7.6 ―++‖和―--‖的重载
时钟类例子
• 运算符前置++和后置++重载为时钟类的 成员函数 • 操作数是时钟类的对象 • 前置单目运算符,重载函数没有形参 • 对于后置单目运算符,重载函数需要有 一个整型形参。 • 实现时间增加1秒钟。
复数类的友元运算符函数
#include<iostream.h> class complex //复数类声明 { public: //外部接口 complex(double r=0.0,double i=0.0) { real=r; imag=i; } //构造函数 friend complex operator + (complex c1,complex c2); //运算符+重载为友元函数 friend complex operator - (complex c1,complex c2); //运算符-重载为友元函数 void display(); //显示复数的值 private: //私有数据成员 double real; double imag; };
7.5 成员运算符函数与友元运算符函数比较
C++的大部分运算符即可以说明为成员函数运算 符,也可以说明成友元函数运算符。 究竟选择哪一种运算符函数好一些,没有定论, 这主要取决于实际情况和程序员的习惯。 如果二元运算符的第一个操作数不是用户自定义 类型,则只能用友元的方式实现,而不能用成 员的方式实现。 下列运算符不能用友元函数来重载: = ( )[ ] -> 成员运算符函数的优点: 体现了面向对象的思想。
第7章
运算符重载
7.1 重载运算符的目的 7.2 运算符重载语法 7.3 成员运算符函数 7.4 友元运算符函数 7.5 成员运算符函数与友元运算符函数比较 7.6 ―++‖和“--‖的重载 7.7 赋值运算符“=‖的重载 7.7 下标运算符”[ ]‖与函数调用运算符”( )‖的重 载 7.9 构造函数用于类型转换 7.10 应用举例
成员和友元运算符函数
class complex{ double re,im; 双目运算符
public:
complex(double r, double I) { re=r; im=i; }
成员函数
complex( ) { re=im=0; } complex operator+(complex ); complex operator++( );
简单复数类的运算符重载(续)
程序输出的结果为: c1=(5,4) c2=(2,10) c3=c1-c2=(3,-6) c3=c1+c2=(7,14) 注:交换c1和c2的位置,不影响结果。
7.4 友元运算符函数
• 重载为友元函数时 参数个数=原操作数个数,且 至少应该有一个自定义类型的形参。 • 友元函数是类以外的函数,调用这种运算符函数时, 所有的操作数都要通过参数传递来获得。 如: class complex {public friend complex operator + (complex c1, complex c2); ……. }
复数类的友元运算符函数(续)
complex operator +(complex c1,complex c2) //运算符重载友元函数实现 { return complex(c2.real+c1.real, c2.imag+c1.imag);
}
complex operator -(complex c1,complex c2) //运算符重载友元函数实现 { return complex(c1.real-c2.real, c1.imag-c2.imag); } // 其它部分同上例
简单复数类的运算符重载(续)
//重载运算符函数的实现 complex complex::operator +(complex c2) { complex c; c.real=c2.real+real; c.imag=c2.imag+imag; return complex(c.real,c.imag); }
简单复数类的运算符重载(续)
void complex::display( ) { cout<<"("<<real<<","<<imag<<")"<<endl; } void main() //主函数 { complex c1(5,4),c2(2,10),c3; //定义复数类的对象 cout<<"c1="; c1.display(); cout<<"c2="; c2.display(); c3=c1-c2; //使用重载运算符完成复数减法 cout<<"c3=c1-c2="; c3.display(); c3=c1+c2; //使用重载运算符完成复数加法 cout<<"c3=c1+c2="; c3.display(); }
《C++面向对象程序设计》教学内容
第1章 C++概述 第2章 类和对象 第3章 面向对象程序设计概述 第4章 进一步学习类和对象 第5章 堆与复制构造函数 第6章 继承性:派生类 第7章 运算符重载 第8章 虚函数和多态性 第9章 模板 第10章 类库和C++的标准模板库STL 第11章 输入输出流 第12章 异常处理
运算符重载
void f( ) { complex a = complex(1, 3.1) ; complex b = complex(1.2, 2) ; complex c = b; a = b+c; b = b+c*a; c = a*b+complex(1,2) ; }
7.2 运算符重载语法
• 运算符重载
• 实现机制
– 运算符重载的实质就是函数重载:每个运 算符对应各自的运算符函数,根据操作数 的不同调用不同的同名函数。 – 将指定的运算表达式转化为对运算符函数 的调用,运算对象转化为运算符函数的实 参。
7.3 成员运算符函数
• 重载为类成员函数时 参数个数=原操作数个数-1 (后置++、--除外) • 当类的对象调用这种运算符函数时,对象中的成 员数据就可以是一个操作数,另一个操作数才通过 参数传递来获得。 • 如: class complex {public complex operator + (complex c2); ……. }
简单复数类的运算符重载
#include<iostream.h> class complex //复数类声明 { public: //外部接口 complex(double r=0.0,double i=0.0) {real=r;imag=i;} //构造函数 complex operator + (complex c2); //+重载为成员函数 complex operator - (complex c2); //-重为载成员函数 void display( ); //输出复数 private: //私有数据成员 double real; //复数实部 double imag; //复数虚部 };
时钟类例子(续1)
#include<iostream.h> class Clock //时钟类声明 { public: //外部接口 Clock(int NewH=0, int NewM=0, int NewS=0); void ShowTime(); void operator ++(); //前置单目运算符重载 void operator ++(int); //后置单目运算符重载 private: //私有数据成员 int Hour, Minute, Second; };
时钟类例子(续3)
void Clock::operator ++(int) //后置单目运算符重载 { Second++; if(Second>=60) { Second=Second-60; Minute++; if(Minute>=60) {Minute=Minute-60; Hour++; Hour=Hour%24; } } cout<<"Clock++: "; }
时钟类例子(续2)
void Clock::operator ++() //前置单目运算符重载函数 { Second++; if(Second>=60) { Second=Second-60; Minute++; if(Minute>=60) { Minute=Minute-60; Hour++; Hour=Hour%24; } } cout<<"++Clock: "; }
时钟类例子(续5)
程序运行结果为:
First time output:23:59:59 Clock++: 0:0:0 ++Clock: 0:0:1
7.7 赋值运算符―=‖的重载
• 如果没有为类显式地定义赋值运算符,编译器 将自动产生一个缺省的赋值运算符函数,它执 行以字节为单位的复制操作。 • 注意operator=()函数的两个重要特点:
• 首先在类定义时说明待重载的运算符,其格式为: 返回值类型 operator op (参数表);
ຫໍສະໝຸດ Baidu
• 然后象定义函数一样定义重载运算符函数。
返回值类型 类名称∷operator op(参数表)
{ //…… 运算符处理程序代码 }
运算符重载的实质
• 必要性
– C++中预定义的运算符其运算对象只能是 基本数据类型,而不适用于用户自定义类 型(如类)