文章目录
1、运算符重载
重载——一名多用。同一个运算符,在不同的场合使用有不同的作用。
2、运算符重载的方法
定义一个重载运算符的函数。运算符重载实质上是函数的重载
一般格式:
函数类型 operator 运算符名称(形参表){对运算符的重载处理}
如:Complex operator +(Complex &c1,Complex &c2);
函数名是operator 运算符名称,即“operator +”,称:“operator +"重载了运算符”+“
参数是两个复数时系统调用重载函数。
普通的原函数:
Complex Complex::complex_add(Complex &c2){
Complex c;
c.real=real+c2.real;
c.imag=imag+c2.imag;
return c;
}
“+”重载函数:
Complex Complex::operator +(Complex &c2){
Complex c;
c.real=real+c2.real;
c.imag=imag+c2.imag;
return c;
}
更简练的写法:
Complex Complex::operator +(Complex &c2){
return Complex(real+c2.real,imag+c2.imag):
}
3、重载运算符的规则
1、C++不允许用户定义新下运算符,只能对已有的C++运算符进行重载
2、C++运行重载的运算符。
表10.1 C++允许重载的运算符
不允许重载的5个运算符:
. | (成员访问运算符) |
---|---|
.* | (成员指针访问运算符) |
:: | (域运算符) |
sizeof | (长度运算符) |
?: | (条件运算符) |
前两个运算符不能重载是为了保证访问成员的功能不能被改变,域运算符和sizeof 运算符的运算对象是类型而不是变量或一般表达式,不具备重载的特征。
3、重载不能改变运算符对象(操作数)的个数
4、重载不能改变运算符的优先级别
5、重载不能改变运算符的结合性
6、重载运算符 函数不能有默认的参数
7、重载的运算符必须和用户的自定义类型的对象一起使用,其参数至少应有一个是类对象。
8、用于类对象的运算符一般必须重载,但有两个例外,“=”和“&”(返回类对象再内存中的起始地址)不必用户重载
9、理论上,可以将一个运算符重载为执行任意 操作
4、运算符重载函数作为类成员函数和友元函数
对运算符重载的函数有两种:
- 把重载函数作为类 成员函数;
- 作为一个普通函数,在类中声明为友元函数。
友元运算符重载函数:
class Complex{
public:
....
friend Complex operator +(Complex &c1,Complex &c2);//友元函数
...
}
Complex operator +(Complex &c1,Complex &c2){//在类外定义的重载函数
return Complex(c1,real+c2.real,c1.imag+c2.imag):
}
对于+运算,是需要两个操作数的,第一种方法定义重载时,有一个参数是隐含的,把this指针指向的对象的成员作为其中一个参数,所以该方法下函数参数只有一个;
而第二种方法是在类外定义的友元函数,就需要两个参数。
第一种方法的“+”左边的一定要Complex类对象,例如:c3=c2+c1;或c3=c1+4;
如果是其他的类型或其他类的对象,就调用不到重载函数。
第二种方法在定义重载函数时,函数的参数类型任意,但在使用时,“+”左边的操作数类型要与第一个参数一致,“+”右边的操作数要和第二个参数类型一致。
- C++规定,“=”、“[]”、“()”、“->”必须作为成员函数重载
- "<<"、">>"、类型转化运算符函数不能定义为类成员函数,只能作为友元函数
- 一般将单目运算符和复合运算符重载为成员函数
- 一般将双目运算符重载为友元函数
5、重载双目运算符
双目运算符(二元运算符):2个参数。
class String{
public:
String(){p=NULL;}
String(char *str);
friend bool operator>(String & string1,String &string2);//声明运算符函数为友元函数
void display();
private:
char *p;
};
String ::String(char *str){p=str;}
void String::display(){cout<<p;}
bool operatro>(String &string1,String &string2){//返回一个bool类型。
if(strcmp(string1.p,string2.p)>0)
return true;
else return else;
}
int main(){
String string1("Hello"),string2("Book");
cout<<(string1>string2)<<endl;//
}
重载方法:先搭框架,逐步扩充,由简到繁,最后完善。边调试,边扩充。
6、重载单目运算符(只有一个操作数)
只有一个操作数,把重载函数重载为类中的成员函数,默认为this 指针指向的对象为唯一操作数。
7、重载流插入运算符“>>“和流提取运算符”<<"
istream &operator >>(istream &,自定义类 &);
ostream& operator<<(ostream &,自定义类&);
7.1重载流插入运算符"<<"
输出自己声明的类的对象的信息
ostream & operator<<(ostream & output,Complex & c){
output<<"("<<c.real<<" +"<<c.imag<<"i)"<<enl;
return output;
}
cout<<c3;//c3是Complex类,调用重载函数,输出(8+14i)
return output的作用:能连续向输出流插入信息,如:cout<<c3<<c2;cout<<c3调用重载函数后将cout的当前值返回,相当于cout(新值)<<c2,此时依旧满足调用重载函数的条件,所以可以让cout连续输出。
7.2重载流提取运算符">>"
istream& operator>>(istream & input,Complex &c){
input>>c.real<<c.imag;
return input;
}
cin>>c1>>c2;//连续输入3 6 4 -10,得到c1=(3+6i) c2=4+-10i)
8、有关运算符重载的归纳
使用运算符重载的具体做法:
- 确定要重载哪个运算符,想应用到哪一个类。重载运算符只能把一个运算符用于一个指定的类,而不是所有类都可以适用。
- 设计运算符重载函数和有关类。
- 实际中,不要求最终用户自己取编写每一个运算符重载函数,有人事先把需要重载 运算符统一放在一个头文件里。
- 使用者需要了解该头文件包含哪些运算符的重载,适用于那些类,有哪些参数。
- 没有现成的就得自己设计,把设计好的保留下来。
9、不同类型数据间的转化
9.1标准类型间的转换
- 隐式类型转换。由编译系统自动完成。
- 显式类型转换。程序员指定的。
显式类型转换的两种形式:类型名(数据),如:int(89.5);
或(类型名)数据。如:(int)89.5;
9.2用转换构造函数进行不同类型数据的转换。
转换构造函数:将一个其他类型的数据转换成一个类的对象。
(只有一个形参),
Complex(double r){real=r;imag=0;}//将double类型的参数转换成Complex类的对象,r为复数的实数,虚部为0
Complex c1(3.5);//建立对象c1,由于只有一个参数,调用转换构造函数。
Complex(3.6);//建立一个无名对象,合法但无法使用;
c1=Complex(3.6);//建立一个无名对象,值为(3.6+0i),把这个无名对象的值赋给c1
“+”重载后,两边都是Complex对象作为操作数。如果要用它来将一个对象和浮点数,相加,可以利用转换构造函数将浮点数进行强制转换,c=c1+Complex(2.5);//合法;
使用方法:
- 先声明一个类
- 在类中定义一个只有一个参数 的构造函数,参数类型是需要转换 类型,在函数体中指定转换的方法
- 在类的作用范围内可以使用以下形式进行类型转换。
类名(指定类型的数据)。
9.3类型转换函数
作用:将一个类的对象转换成另一个类型的数据。
opertor 类型名(){
实现转换的语句
}
//将一个Complex类对象转换成一个double数,
operator double(){return real;}//返回double类型real的值。
- 类型转换函数只能作为成员函数,转换的主体是本类的对象,不能作为友元函数或普通函数。
- 隐式调用,如果运算符左右不符合,需要将double转换成对象时,系统自动调用,否则不调用。
- 又称“类型转换运算符函数”,“类型转换运算符重载函数”
- d1=d2+c1;
首先,看重载+,”+“左为double类型,右为Complex类型。不符合。
然后,发现有重载double,调用。
完成。 - c2=c1+d2,有转换构造函数和重载+(作为Complex类友元,即左侧一定要是Complex):
首先,有重载+,判断:+左边是对象,满足;右边不是对象,不满足,不符合。
再看是否有double重载,没有。
最后去找转换构造函数,转换Complex(d2),建立临时的对象,此时符合重载+,调用重载+。
如果运算符函数重载为成员函数,第一个参数必须是本类 对象。当第一个操作数不是类对象时,不能将运算符函数重载为成员函数。如果将运算符“+”函数重载为类的成员函数,交换律不可用。
一般将双目运算符函数重载为友元函数,单目运算符则多重载为成员函数。
如果一定要将双目运算符重载为成员函数,第一个操作数又不是类对象时,只能再重载一个“+”函数,第一个参数为double类型,并重载为友元函数。
如果要使用类型转换函数,应删去“+”重载函数。