第十讲:重载
第十讲:重载
- 运算符重载的方法
-
运算符重载函数作为类成员函数和友元函数
-
运算符重载的规则
- 什么是运算符重载
重载,就是重新赋予新的含义。函数重载就是对一个已有的函数赋予新的含义,使之具有新的功能。
重载也就是一名多用。
运算符重载:严格运算符具有多重含义。
例如: “<<“ 既是位运算符又是与cout 配合使用的流插入运算符。
- 什么是运算符重载
-
用函数实现复数重载(没有运算符重载)
#include <iostream.h>
class complex //类定义
{public:
complex ( ) { real = 0;image = 0; }
complex (double r, double i)
{ real = r; image = i; }
complex add (complex &c2);
void display( );
private:
double real, image;
};
complex complex::add (complex &c2)
{ complex c;
c.real = real + c2.real;
c.image = image + c2.image;
return c;
}
void complex::display( )
{ cout << “( “ << real << “,”
<< image << “i )” << endl;
}
Int main( )
{ complex c1(3,4), c2(5,-10), c3;
c3=c1.add (c2);
cout << “c1 = “; c1.display( );
cout << “c2 = ”; c2.display( );
cout << “c1+c2 = “; c3.display( );
return 0;
}
特点:烦琐、不方便。可不可以用 c3=c1+c2 的形式来表达呢?
只要对“+”号进行重载,复数加法就可以写成这种形式c3=c1+c2 。
- 运算符重载的方法
1、运算符重载的方法:
1)定义一个重载运算符的函数;
2)在需要执行重载的运算符时,系统就自动调用该重载的运算符函数
2、重载运算符函数的一般格式:
函数类型 operator 运算符名称 ( 形参表列 )
{ 对运算符的重载处理
}
例如:Complex operator+ (Complex &c1,Complex &c2);
注意:
operator 是关键字,专门用于定义重载运算符。
运算符名称就是C++提供给用户的预定义名称。如:+、-、*、/、<、<<、>>、>等等。
函数名是由operator和运算符组成,上面operator+就是函数名。
# include <iostream.h>
// 例4-2:改写例4-1,重载运算符“+”用于2个复数加法
class complex // 类定义
{ double real, image;
public:
complex (double r = 0, double i = 0)
{ real = r; image = i;}
void show( )
{cout<<real<<“+”<<image<<"i"<<endl; }
complex operator+( complex &c2); // 成员函数作为运算符重载函数
};
complex complex::operator+ ( complex &c2) // +重载定义
{ complex c;
c.real = real + c2.real;
c.image = image + c2.image;
return c ;
}
void main( )
{ complex c1(3, 4), c2(5, -10), c3;
c3 = c1 + c2; // 系统自动调用operator+函数,把c1、 c2作实参。
c3.show( ); }
比较例4.1和4.2:
operator+函数取代了add函数
c3=c1+c2取代了c3=c1.add c2)
在将运算符+重载为类的成员函数后,C++编译系统将程序中的表达式c1+c2解释为c1.operator+(c2),即以c2为实参调用c1的运算符重载函数operator+( complex &c2),进行求值.
问题:都能实现结果,为什么要对运算符重载?
使用运算符重载能使 运算更丰富。
在例4.2中
C3=3+c2; // 错
C3=complex(3,0)+c2; // 对
注意:
运算符被重载后,原有功能仍然保留,没有丧失或改变。
运算符重载对C++程序设计的意义:把运算符重载和类结合起来,可以在C++程序中定义出很多有实用意义而使用方便的新的数据类型,使C++具有更强大的功能,更好的可扩充性和适应性.
运算符重载的规则
1)C++不允许用户自己定义新的运算符,只能对已有的C++运算符进行重载。
2)C++不允许重载的运算符:大多数C++运算符都允许重载,不能重载的运算符只有5个:
“.” :成员访问运算符;
“.*” :成员指针访问运算符;
“::” :域运算符;
“sizeof” :长度运算符;
“?:” :条件运算符。
3)重载不能改变运算符运算对象(即操作数)的个数。例如:双目运算符不能变成三目运算符。
4)重载不能改变运算符的优先级。
5)重载不能改变运算符的结合性。比如,从右至左运算的赋值号,重载后不能变成从左至右运算的顺序。
6)重载运算符的函数不能有默认的参数。否则就改变了运算符参数的个数不变的规定。
7)重载运算符函数的参数不能全是标准数据类型,以防止用户修改用于标准类型数据的运算性质,避免混乱。如:
int operator + (int a, int b ) { return a – b; }
如果有表达式4+3,它的结果是7 呢还是1 ?
8)用于类对象的运算符一般必须重载,但运算符“=”和“&”,用户不必重载。
=:用于同类对象赋值
&:用于取对象在内存中的地址。
9)运算符重载应使其类似于标准数据类型
10)运算符重载函数可以是:
类的成员函数、 类的友元函数、普通函数
10.4 运算符重载函数作为 类成员函数、友元函数、普通函数
1、类成员函数:例4.2中,重载函数operator+作为complex类的成员函数。
问题:“+”是双目运算符,为什么例4.2中重载函数只有一个参数?
实际上,运算符重载函数有两个参数,由于重载函数是complex类中的成员函数,有一个参数是隐含的,运算符函数是用this指针隐式地访问类对象的成员。其中:重载函数operator+访问了两个对象的成员,一个是this指针指向的对象中的成员,一个是形参对象中的成员。
2、运算符重载函数作为类友元函数。
例4.3:复数加法,将运算符+重载为友元函数。
#include <iostream.h>
class complex //类定义
{ private: double real,image;
public:
complex(double r=0,double i=0)
{real=r; image=i;}
void show()
{ cout<<real<<((image>=0)?'+':'\a') <<image<<'i'<<endl; }
friend complex operator+(complex &c1,complex &c2);
// 类的友元函数,2个参数c1,c2
};
complex operator+ (complex &c1,complex &c2)
{ complex c;
c.real=c1.real+c2.real; c.image=c1.image+c2.image;
return c;
}
void main()
{ complex c1(1.5,3),c2(1,4.5);
complex c3; c3=c1+c2;
c3.show();
}
在将运算符“+”重载为非成员函数后,C++编译系统将程序中的表达式c1+c2解释为operator+(c1,c2)
问题:为什么把运算符函数作为友员函数?
因为运算符函数要访问为对象中的成员,如果运算符函数不是类的友员,而是一个普通函数,它就没有权限访问类的私有成员。
3、运算符+重载为普通函数如何实现?
例:复数加法,将运算符+重载为普通函数。
注意:
1)普通函数只能调用公有数据成员。
2)友元函数要在类内声明。
# include <iostream.h>
class complex
{public: //公有成员
double real, image;
complex (double r = 0, double i = 0) // 构造函数
{ real = r; image = i;}
void show( )
{cout<<"real = "<<real<<' '<<"image = "<<image<<endl;
}
};
complex operator+ (complex &c1, complex &c2)
//普通函数,2个参数c1 , c2
{complex c;
c.real =c1.real + c2.real; c.image = c1.image + c2.image;
return c;
}
void main( )
{ complex ob1(1.5, 3.0), ob2(1.0, 5.0);
complex sum; sum = ob1 + ob2;
sum.show( );
}
10.4 运算符重载函数作为 类成员函数、友元函数、普通函数
1、运算符重载函数作为普通函数:
极少使用,因为它不能只访问类的私有数据成员。
2、运算符重载函数作为类成员函数:
可以通过this指针*访问本类数据成员,少写一个函数参数,但必须要求表达式第一个参数是一个类对象而且与运算符函数类型相同。因为必须通过类对象去调用该类的成员函数,而且只有运算符重载函数返回值与该类对象同类型,运算结果才有意义。
3、运算符重载函数作为友元函数: 如果运算符重载函数操作结果不是原来的类类型,而运算符重载函数又要操作类的私有数据成员,则必须声明运算符重载函数是 类的友员函数。(常用)
#include <iostream.h> //例4.3-1
class complex
{public:
double real, image;
complex (double r = 0, double i = 0)
{ real = r; image = i;}
friend int operator+ (int c1, complex &c2); //友员函数声明
friend int operator+ (complex &c2,int c1 ) ;
};
int operator+ (int c1, complex &c2) //友员函数定义
{int c; c=c1+c2.real;
return c; }
int operator+ (complex &c2,int c1 ) //友员函数定义
{int c; c=c1+c2.real;
return c; }
int main( )
{ complex ob2(1, 5.0); int s;
s = 3+ ob2; //运算符重载
cout<<"s="<<s<<endl;
s = ob2+3; //运算符重载
cout<<"s="<<s<<endl;
return 0;
}
10.5 重载双目运算符
双目运算符(也叫二元运算符)有两个操作数,通常在运算符的左右两侧。如 a=b、i<10 等。重载双目运算符时,函数中应该有两个参数。
例4.4-1: 定义一个字符串类String。
include
//例4.4-1 定义一个字符串类String。
using namespace std;
class String
{public:
String(){p=NULL;}
String(char *str);
void display();
private: char *p;
};
String::String(char *str) {p=str; }
void String::display()
{cout<
#include <iostream.h> // 重载运算符“ >”
#include <string.h>
class String
{public: String(){p=NULL;} String(char *str);
friend bool operator>(String &st1,String &st2);
// 利用友元函数重载>
void display();
private: char *p; };
String::String(char *str) {p=str;}
void String::display() {cout<<p;}
bool operator>(String &st1,String &st2)
{ if(strcmp(st1.p,st2.p)>0) return true;
else return false;
}
int main()
{String s1("Hello"),s2("Book");
cout<<(s1>s2)<<endl;
return 0; }
例4.4-3,在4.4-1基础上,重载运算符==,>,<
#include <iostream.h>
#include <string.h>
class String
{public: String(){p=NULL;} String(char *str);
friend bool operator>(String &s1,String &s2);
friend bool operator<(String &s1,String &s2);
friend bool operator==(String &s1,String &s2);
void display();
private: char *p;
};
String::String(char *str) {p=str;}
void String::display() {cout<<p;}
bool operator>(String &s1,String &s2)
{if(strcmp(s1.p,s2.p)>0) return true;
else return false; }
bool operator<(String &s1,String &s2)
{if(strcmp(s1.p,s2.p)<0) return true;
else return false; }
bool operator==(String &s1,String &s2)
{if(strcmp(s1.p,s2.p)==0) return true;
else return false; }
int main()
{String s1(“Hello”),s2(“Book”),s3(“Computer");
cout<<(s1>s2)<<endl; cout<<(s1<s3)<<endl; cout<<(s1==s2)<<endl; return 0; }