第八讲 运算符重载
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
除此之外,下两种情况编译器自动调用复制构造函数: 1、类对象作参数传递; 2、返回一个类对象。
Complex operator+(Complex com1, Complex com2) { return Complex(com1.rpart+com2.rpart, com1.ipart+com2.ipart); }
(a.operator-( )).operator+(b) sizeof
不能重载的运算符:. , * , :: , ? , 不能重载的运算符 重载应注意的问题: 重载应注意的问题: 1、优先级和结合顺序不变 2、不能改变目数
3、类外定义至少有一个相应类的参数
class x { public: int i; }; X operator+(const X& x1, const X& x2) { 外部函数,若写为: 外部函数,若写为: X temp; X operator +(int i1,int i2) temp.i=x1.i+x2.i; 内部类型, 内部类型,用户不能改变 return temp; }
问题?——解决方法? 问题?——解决方法? 解决方法
访问私有成员 友员函数
用于Complex的其它算术运算符重载: 用于Complex的其它算术运算符重载: Complex的其它算术运算符重载
class Complex { //…… friend Complex operator *(double, Complex com); public: Complex operator*(double d) { //…… } //…… }; Comple operator *(double d, Complex com) { //…… } Complex a, b, c; a=3*b; a=b+c*3*5;
8.2.2 重载赋值运算符
编译器缺省的赋值运算符是逐位把源对象拷贝到目标对象。
Complex c1, c2; c1=c2;
类Cmessage的问题: #include<iostream.h> #include<string.h> class CMessage { private: char *buffer; public: CMessage( ) { buffer=new char('\0'); } ~CMessage( ) { delete [ ] buffer; } void Display( ) { cout<<buffer<<endl; } void Set(char *string) { delete [ ] buffer; buffer= new char[strlen(string)+1]; strcpy(buffer, string); } };
撤销c2也会出现 撤销c2也会出现 c2 同样的问题
class CMessage { //…… public: void operator=(const CMessage& Message) { delete [ ] buffer; buffer= new char[strlen(Message.buffer)+1]; strcpy(buffer, Message.buffer); } //…… };
赋值运算符一般 用预定义的
单目运算符重载: 单目运算符重载:
Complex Complex:: operator-() { Complex temp; temp.rpart=-rpart; temp.ipart=-ipart; return temp; }
单目无参数 双目一个参数
Complex c=-a+b;
#include <iostream.h> class HowMany{ public: HowMany() {cout<<"Constructor"<<endl;} ~HowMany() {cout<<"Disconstructor"<<endl;} HowMany(const HowMany& ) {cout<<"Copy Constructor"<<endl;} void print(){cout<<"Member function"<<endl;} }; HowMany f(HowMany x) { x.print(); return x; } void main(){ HowMany h; HowMany h1=f(h); h1.print(); HowMany h2; h2=f(h); }
9、编译器预定义了“=”, “&”, “,(顺序)”, 三种运算符,不必重载可直接使 用
class x { //…… private: void operator= (const X&); void operator& ( ); void operator, (const X&); 说明为私有限制对它们的使用 //…… }; void f(X a, X b) { a=b; X *p=&a; }
第八讲
运算符重载
用户定义类型用运算符表示操作
8.1 运算符重载
运算符——一种函数;对于类对象,用户可重新定义运算符函数。
#include<iostream.h> class Complex { private: double rpart, ipart; public: Complex ( ) { rpart=ipart=0.0; } Complex(double rp, double ip) { rpart=rp; ipart=ip; } Complex add(const Complex &com) { Complex temp; temp.rpart=com.rpart+rpart; temp.ipart=com.ipart+ipart; return temp; } void print_complex() { cout<<rpart<<','<<ipart<<endl; } };
6、单目后缀运算符@:成员函数带一个int参数;外部函数带二个参数
aa@ aa@ aa.operator( int ) operator(aa, int)
7、只能重载已有的运算符,不能创造新的
8、成员和外部运算符函数可重载(多个同名运算符函数) class x { public: double operator+(double) { //…… } double operator+(int) { //…… } }; float operator+(X, int) { //…… } X x1, x2, x3; x2+3.0; x2+3;
void main( ) { CMessage c1; c1.Set("initial c1 message"); c1.Display( ); CMessage c2; c2.Set("initial c2 message"); c2.Display( ); c1=c2; c1.Display( ); }
自身赋值问题 :
Cmessage& CMessage::operator=(const CMessage& Message) { if( &Message==this) return *this; delete [ ] buffer; buffer= new char[strlen(Message.buffer)+1]; strcpy(buffer, Message.buffer); return *this; }
源自文库
CMessage c1, c2; c1=c2; c2.Set("newstring"); c2.Display(); c1.Display(); c1.buffer c1.buffer c2.buffer c2.buffer c2.buffer c1.buffer
解决方法——赋值运算符重载 解决方法——赋值运算符重载
Complex a(10,7), b(3,5); Complex c=a.add(b); c.print_complex();
希望c=a+b; 希望
复数加法运算重载符函数: class Complex { //…… public: 公有成员函数 Complex operator+(Complex &com) { Complex temp(rpart+com.rpart, ipart+com.ipart); return temp; } //…… Complex a(10,7), b(3,5), c; }; a.operator+(b) c=a+b;
8.2
算术运算符、 算术运算符、赋值运算符和逻辑运算符的重载
8.2.1 重载算术运算符
class Complex { //…… public: Complex operator+(double) { //…… } //…… }; Complex a, b; a=b+10.0; a=10.0+b; b.operator(10.0) 10.0.operator(b)
c1.buffer c1.buffer
c2.buffer
c2.buffer
注意:=运算符重载必须用成员函数,不能非成员友元形式; 连串赋值要返回对象的引用
CMessage& operator=(const CMessage& Message) { delete [ ] buffer; buffer= new char[strlen(Message.buffer)+1]; strcpy(buffer, Message.buffer); return *this; } void main( ) { CMessage c1; c1.Set("initial c1 message"); c1.Display( ); CMessage c2; c2.Set("initial c2 message"); c2.Display( ); CMessage c3; c3=c1=c2; c3.Display( ); }
8.2.3 复制构造函数(带引用此类型的单参数的构造函数)
class x { //…… public: X( ) { //…… }; X(X& xx) { 复制构造函数, //…… 复制构造函数,初始化对象时调用 } //…… }; X x1; X x2(x1); X x3=x1; 等价, x1初始化x2和 等价,用x1初始化x2和 初始化x2 x3,=并不调用赋值运算符 x3,=并不调用赋值运算符
x1=x2+x3; operator+(x2, x3);
4、双目运算符@:成员函数只带一个参数;外部函数带两个参数
aa@bb aa@bb aa.operator@(bb) operator@(aa, bb)
5、单目前缀运算符@:成员函数不带参;外部函数带一个参数
@aa @aa aa.operator@( ) operator@(aa)
运算符成员函数——调用成员函数的对象隐式成为表达式的第一个运算数 运算符成员函数——调用成员函数的对象隐式成为表达式的第一个运算数 —— 外部运算符函数——其第一个参数直接对应表达式的第一个运算数; 外部运算符函数——其第一个参数直接对应表达式的第一个运算数; ——其第一个参数直接对应表达式的第一个运算数
解决此问题—— 函数重载: 解决此问题——非成员函数重载: —— 函数重载
Complex operator+(double d, const Complex &com) { Complex temp; temp.rpart=d+com.rpart; temp.ipart=com.ipart; return temp; }
若未定义,编译器生成缺省的复制构造函数( 若未定义,编译器生成缺省的复制构造函数(与 缺省的赋值运算符一样,逐位拷贝)。 缺省的赋值运算符一样,逐位拷贝)。 所以, 中含有指针数据成员,并要为它动态分配空间时,一般来说, 所以,当类 X 中含有指针数据成员,并要为它动态分配空间时,一般来说, 中应定义以下几个函数: 类 X 中应定义以下几个函数: 初始化构造函数; 初始化构造函数; 复制构造函数; 复制构造函数; 赋值运算符函数; 赋值运算符函数; 析构函数; 析构函数;