当前位置:文档之家› 重载实例

重载实例

一、为什么要重载操作符1.操作符重载就是把操作符比如+,-,*,/这些运算符赋于新的意义。

2.操作符重载的目的:C++有许多内置的数据类型,包括int,char,double等,每一种类型都有许多运算符,例如加+,减,乘,除等。

当用户定义了类的对象时,两个对象之间是不能进行这些操作的,比如hyong类的对象a+b,这样的语句如果没有重载+运算符就会出错。

但C++允许用户把这些运算符添加到自已的类中以方便类对象之间的运算就像内置类型的运算一样方便,比如对象a+b这样就很明白更容易懂,当然也可以在类中定义一个对象间相加的函数,比如 a.add(b)调用函数add()以实现两个对象a和b相加,但是这条语句没有比a+b更容易让人理解。

3.怎样实现操作符重载:要实现操作符重载就要使用操作符重载函数,操作符重载函数用关见字operator实现,其形式为:反回类型 operator 操作符 (参数列表){}。

操作符重载函数是一个函数,只不过这个函数的函数名为operator再加上后面要重载的操作符而已,比如要重载+号,则: hyong operator +(hyong m){}这就声明了一个反回类型为hyong的操作符函数,其函数名为operator +4.作为类的成员和友元或者独立于类的区别当操作符重载函数作为类的成员函数时,操作符重载函数的参数会比作为友元或者独立于类的操作符重载函数少一个参数,因为操作符重载类成员函数把调用该函数的第一个类的对象作为函数的第一个参数,也就是隐含的this指针指向调用该函数的第一个对象,所以会少一个参数。

5.调用操作符重载函数的方式:5.1 调用类中的操作符重载函数的方法:当调用类中定义的操作符重载函数时最左边的对象是调用操作符重载函数的对象。

比如在类hyong中重定义的+操作符 hyong operator +(hyong m){},有类hyong的对象m和n则调用操作符重载函数的方法有m+n和m.operator +(n),前一条语句会自动转换为后面这条语句,且m+n的表达式中最左边的对象是调用操作符重载函数的对象,而最右边的那个将被作为参数传送。

也就是说 n+m会转换成n.operator +(m)。

要记住当调用类中定义的操作符重载函数时最左边的对象是调用操作符重载函数的对象。

5.2 调用友元或独立的操作符重载函数的方法:当调用类的友元操作符重载函数或独立的操作符函数时语句m+n会转换为显示的调用方式,比如有友元或独立操作符重载函数hyong operator +(hyong a, hyong b){}则当出现m+n时会转换成语句operator +(m, n)表达式的第一个对象传给第一个参数,第二个对象传给第二个参数。

6.需把其作为类的友元或者类的成员一般来说操作符重载函数一般不要求作为类的成员函数或者是友元函数,一般情部下可以将操作符重载函数作为类的成员函数。

但是有一种情况必须要求操作符函数作为类的友元函数或者是独立的函数,就是一个内置类型和对象相加的情况。

比如有语句m+1和1+m第一条可以在类中定义操作符函数的形式为hyong operator +(int i){},语句m+1可以调用这个函数是正确的,但对于1+m 就不能调用这个函数了,因为类中的操作符重载函数是最左边的对象是调用该函数的对象,但 1+m最左边的是一个内置整型类型1,所以不会调用这条语句,对于这种语句就只能把操作符重载函数定义为独立的函数或类的友元函数即形如hyong operator +(int i , hyong a){}这样1+m就会转换成operator +(1, m)这样就是正确的。

当然如果这个操作符重载函数需要访问类中的私有成员时,就应把该函数定义为类的友元函数,如果不需要访问类中的私有成员,则可以定义为友元也可以定义为独立函数。

7.必须把它作为类成员函数的运算符有:(),[],->和任何赋值运算符,重载这些运算符时必须把操作符函数声明为类的成员函数。

8.重载操作符的限制:8.1 并不是所有的操作符都能被重载。

除了. ,.* ,:: ,? : ,sizeof,typeid这几个运算符不能被重载,其他运算符都能被重载8.2 重载不能改变该运算符用于内置类型时的函义,程序员不能改变运算符+用于两个int型时的含义。

8.3 运算符函数的参数至少有一个必须是类的对象或者类的对象的引用。

这种规定可以防止程序员运用运算符改变内置类型的函义。

8.4 重载不能改变运算符的优先级。

8.5 重载不能改变运算符的结合律。

8.6 重载不能改变运算符操作数的个数。

比如+需要两个操作数,则重载的+也必须要有两个操作数。

9.反回类型问题在某些情况下操作符函数必须反回一个对象类型作为反回值,比如有hyong的对象a,b,c则语句a=b+c其中重载的+操作符就必须反回一个 hyong类型的一个对象,以便赋给对象a,不然该语句就会出错。

当然你可以在语句中反回一个临时对象,也可以反回一个对象的引用,或者反回this指针,不过反回临时对象会浪费内存开销,所以最好反回类对象的一个引用。

10.参数传递问题操作符函数可以按值传递也可以按引用传递,这根据操作符而定,比如对于+运算符既可以把对象按值传递给操作符函数也可以按引用传递给操作符函数,而且+操作符不会改变原操作数的值,所以应把传递类型声明为const,比如hyong operator +(const hyong &a, const hyong &b){}。

但对于要改变其自身值的操作符比如++运算符,就必须传递引用,且不能把该引用声明为const 类型,因为如果操作数按值传递的话,传递给操作数函数的将是一个对象的副本,两个副本是独立的,不能改变到原对象的值,所以应按引用传递对象,比如hyong operator ++(hyong &a){}。

[编辑本段]二、载一元运算符++1.注意++有前缀和后缀之别,前缀形式是变量先加1然后执行表达式,而后缀形式则是先执行表达式然后再使变量加1,所以在执行后缀的++运算符时应先反回对象的原始值,然后才对对象加1。

2.默认的带有一个参数的++运算符函数是前缀++运算符,要重载后缀的++运算符必须采用另一种方式实现。

重载后缀的++运算符时应给函数多增加一个int参数,该int参数不会使用,应忽略他,该参数只是为了让编译器区分++运算符的前缀和后缀形式之间的区别。

比如重载后缀++运算符的友元函数形式为hyong operator ++(hyong &a, int i){}后面的参数int i没有实际意义,应忽略他。

例:重载++运算符的例子class A{public: int b; A(){b=0;} A(int i){b=i;} ~A(){cout<<"xi"<<"\n";} const A & operator ++( ){ ++b; return *this;} }; //定义前缀形式的++运算符,函数的反回类型既可以反回引用也可以是反回值,但反回引用不会增加内存开销。

反回类型可以是任意的,比如可以是int型,也可以是void,即没有反回值,但这里的反回类型必须是类类型A,因为在main函数中表达式用于赋值运算符的左边,且把结果赋给了一个类A的对象。

反回const的原因是防止++++k这样的情况出现,有const就不能再改变反回对象的值即不能再对++k 作增量运算。

const A & operator ++(A &j, int i) //定义独立的后缀形式的++运算符,这里必须把第一个参数声明为对对象的引用,因为++运算符会改变原始对象的值,如果不是引用就不能改变原始对象的值,也就达不到++运算符的笑果。

注意int i参数是不使用的,只是让编译器区分是前缀还是后缀的++运算符。

{A t(j); //因为后缀形式的++运算符是先执行表达式后进行增量运算,所以这里应生成一个临时对象以便反回对象的原始值++j.b; //注意,因为独立函数既不是类的友元又不是类的成员,所以这里没有this指针,也不能直接访问类的成员。

return t;} //反回对象t,这里会生成一个临时对象。

int main(){ A m,n,k;m=++k; //调用前缀形式的++类成员运算符函数,语句等价于m=k.operator ++();因为前缀的++是类的成员,所以只能用点运算符调用,形如operator ++(k)将是错语的。

cout<<m.b<<k.b; //输出11,前缀++是先使变量加再执行表达式,即对象k 的值先加,然后再赋给对象mn=k.operator ++ (); //显示调用前缀的++类成员运算符函数。

同m=k++。

cout<<n.b<<k.b; //输出22。

n=k++; //调用后缀形式的独立++运算符函数,该语句等价于n=operator ++(k,1),其中后面的是没有意义的参数,只是为了让编译器区别是前缀还是后缀cout<<n.b<<k.b; //输出23,注意,这里n的值没有增加,因为后缀++是先执行表达式后使变量加。

n= operator ++(k,1); //显示调用后缀的++独立运算符函数,同n=k++。

注意整形实参在这里没有实用价值,但必须得有,以便指明是调用的后缀++形式。

cout<<n.b<<k.b; } //输出34。

[编辑本段]三、重载二元运算符+要注意重载二元运算符时如果有形如1+m这种类型的表达式就必须把该操作符函数定义为非类的成员的形式。

因为类中的操作符重载函数是最左边的对象是调用该函数的对象class A{public: int b; A(){b=0;} ~A(){cout<<"xi"<<"\n";}explicit A(int i){b=i;} //这里需要explicit关见字以防止自动的隐式类型转换,不然语句const A &operator +(const A &j)和friend const A&operator +(const A &j,const int i)将出错二义性问题。

也就是第一个操作符函数可以用隐式类型转换用语句m+3来调用。

//const A & operator +(const A &j){b=b+j.b;return *this;} //对于+操作符不会改变被加的操作数的值,但这里改变了调用该函数的对象的值,最好不要这样做。

相关主题