来源http://www.cctry.com/forum.php?mod=viewthread&tid=79053#lastpost
运算符重载
一.什么是运算符重载?
运算符重载的方法是定义一个重载运算符的函数,在需要执行被重载的运算符时,系统就自动调用该函数,以实现相应的运算。也就是说,运算符重载是通过定义函数实现的。运算符重载实质上是函数的重载。
重载运算符的函数一般格式如下:
函数类型 operator 运算符名称 (形参表列)
二.运算符重载的意义 ?
运算符重载是一种特殊的函数重载。例如int a,b;则求a+b值时,在编译过程中使用的是函数调用:opertor+(a,b).主要作用就是使程序更加简洁,减少编程时间。
的确是一样的,比如你重载了加号,其实是同样可以定义add()函数来完成相同的操作。
重载是为了让运算比较符合人的思维C++有许多内置的数据类型,包括int,char,double等,每一种类型都有许多运算符,例如加+,减,乘,除 等。 当用户定义了类的对象时,两个对象之间是不能进行这些操作的,比如hyong类的对象a+b,这样的语句如果没有重载+运算符就会出错。但C++允许 用户把这些运算符添加到自已的类中以方便类对象之间的运算就像内置类型的运算一样方便,比如对象a+b这样就很明白更容易懂,当然也可以在类中定义一个对 象间相加的函数,比如a.add(b)调用函数add()以实现两个对象a和b相加,但是这条语句没有比a+b更容易让人理解
三 .可以重载的运算符有:
算术运算符:+,-,*,/,%,++,--;
位操作运算符:&,|,~,^,<<,>>
逻辑运算符:!,&&,||;
比较运算符:<,>,>=,<=,==,!=;
赋值运算符:=,+=,-=,*=,/=,%=,&=,|=,^=,<<=,>>=;
其他运算符:[],(),->,,(逗号运算符),new,delete,new[],delete[],->*。
不能重载的运算符只有5个:
类属关系运算符“.”,成员指针运算符“*”,作用域分辨符“::”,sizeof运算符和三目运算符“?:”。
(2)重载之后运算符的优先级和结合性都不变。
(3)四个“不能改变”
·不能改变运算符操作数的个数;
·不能改变运算符原有的优先级;
·不能改变运算符原有的结合性;
·不能改变运算符原有的语法结构。
(4)至少要有一个操作对象是自定义类型。
(5)重载的运算符含义必须清楚,不能有二义性。
(6)、必须重载为成员函数的运算符: [], (), –>, =
(7)、在类成员函数中重载运算符是不允许返回引用的,会出现“返回局部变量的地址”警告
(8)、cout << f1 << f2;
//用重载运算符表示,只能通过友员来实现
//如果要用成员函数,则会有cout.operator<<(const F& f),所以这是不
// 可能的.因此只能用友员来实现,operator<<(cout,f)
// 而cout是ostream型的,因此有以下标准格式.注意不能加const,因为
//cout是要改变的,会改变里的缓冲成员.
ostream& operator<<( /* 不能加const */ ostream& cout, constF&) //输出运算符的标准重载格式.
friend istream& operator>>(istream& is, F& f){ }//输入运算符重载标准格式
四.重载运算符的二种方法
1运算符是类成员函数
要实现操作符重载就要使用操作符重载函数,操作符重载函数用关键字operator实现,其形式为:返回类型 operator 操作符 (参数列表){}。操作符重载函数是一个函数,只不过这个函数的函数名为operator再加上后面要重载的操作符而已,比如要重载+号,则: hyong operator +(hyong m){}这就声明了一个返回类型为hyong的操作符函数,其函数名为operator +
class CTest
{
int i;
CTest operator +(int i)
{
CTest m_test=*this;
m_test.i =this->i+i;
return m_test;
}
}
那么调用时就可以这样:
Ctest m_test1,m_test2;
m_test2=m_test1+1; 也可以这样调用 m_test2=m_test1.operator(1);
2运算符是类的友元函数
Class CTest
{
Friend CTest operator+(CTest TA,CTest TB);
public:
CTest()
{
i=2;
}
public:
int i;
}
CTest operator+(CTest TA,CTest TB)
{
CTest TC
TC.i= TA.i+TB.i
return TC;
}
int main()
{
CTest a,b,c
c=a+b;
}
参数个数的限定
非成员函数:
单目运算符:参数表中只有一个参数;
双目运算符:参数表中只有两个参数
成员函数:
单目运算符:参数表中没有参数;
双目运算符:参数表中只有一个参数
重载运算符为成员函数后,当调用该运算符时,左操作数必须是该类的实例。友元函数中流参数定义第一个参数.才能调用cout<<obj;而成员函数流参数不是第一个参数,调用时应该是obj<<cout;(加入允许重载为成员函数的话)
虽然不能“重载”为成员函数,但是可以定义为新的成员函数,只不过使用习惯和常例不符而已。看下面的代码:
class test{
public:
ostream& operator<<(test& a);
test(){ name = 1;}
private:
int name;
};
ostream& test::operator<<(test& a)
{
cout<<a.name<<endl;
}
int main(int argc, char* argv[])
{
test *t = new test();
(*t)<<(*t);
system("pause");
exit(0);
}
3.作为类的成员和友元或者独立于类的区别
当操作符重载函数作为类的成员函数时,操作符重载函数的参数会比作为友元或者独立于类的操作符重载函数少一个参数,因为操作符重载类成员函数把调用该函数的第一个类的对象作为函数的第一个参数,也就是隐含的this指针指向调用该函数的第一个对象,所以会少一个参数。
4.调用操作符重载函数的方式:
4.1 调用类中的操作符重载函数的方法:当调用类中定义的操作符重载函数时最左边的对象是调用操作符重载函数的对象。比如在类hyong中重定义的+操作符 hyong operator +(hyong m){},有类hyong的对象m和n则调用操作符重载函数的方法有m+n和m.operator +(n),前一条语句会自动转换为后面这条语句,且m+n的表达式中最左边的对象是调用操作符重载函数的对象,而最右边的那个将被作为参数传送。也就是说 n+m会转换成n.operator +(m)。要记住当调用类中定义的操作符重载函数时最左边的对象是调用操作符重载函数的对象。
4.2 调用友元或独立的操作符重载函数的方法:当调用类的友元操作符重载函数或独立的操作符函数时语句m+n会转换为显示的调用方式,比如有友元或独立操作符重 载函数hyong operator +(hyong a, hyong b){}则当出现m+n时会转换成语句operator +(m, n)表达式的第一个对象传给第一个参数,第二个对象传给第二个参数。
5.需把其作为类的友元或者类的成员
一般来说操作符重载函数一般不要求作为类的成员函数或者是友元函数,一般情况下可以将操作符重载函数作为类的成员函数。但是有一种情况必须要求操作符函数 作为类的友元函数或者是独立的函数,就是一个内置类型和对象相加的情况。比如有语句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)这样就是正确的。当然如果这个操作符重载函数需要访问类中的私有成员时,就应把该函数定义为类的友元函数,如果不需要访问类中的私有成员,则可以定义 为友元也可以定义为独立函数。
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){}。
运算符重载
一.什么是运算符重载?
运算符重载的方法是定义一个重载运算符的函数,在需要执行被重载的运算符时,系统就自动调用该函数,以实现相应的运算。也就是说,运算符重载是通过定义函数实现的。运算符重载实质上是函数的重载。
重载运算符的函数一般格式如下:
函数类型 operator 运算符名称 (形参表列)
二.运算符重载的意义 ?
运算符重载是一种特殊的函数重载。例如int a,b;则求a+b值时,在编译过程中使用的是函数调用:opertor+(a,b).主要作用就是使程序更加简洁,减少编程时间。
的确是一样的,比如你重载了加号,其实是同样可以定义add()函数来完成相同的操作。
重载是为了让运算比较符合人的思维C++有许多内置的数据类型,包括int,char,double等,每一种类型都有许多运算符,例如加+,减,乘,除 等。 当用户定义了类的对象时,两个对象之间是不能进行这些操作的,比如hyong类的对象a+b,这样的语句如果没有重载+运算符就会出错。但C++允许 用户把这些运算符添加到自已的类中以方便类对象之间的运算就像内置类型的运算一样方便,比如对象a+b这样就很明白更容易懂,当然也可以在类中定义一个对 象间相加的函数,比如a.add(b)调用函数add()以实现两个对象a和b相加,但是这条语句没有比a+b更容易让人理解
三 .可以重载的运算符有:
算术运算符:+,-,*,/,%,++,--;
位操作运算符:&,|,~,^,<<,>>
逻辑运算符:!,&&,||;
比较运算符:<,>,>=,<=,==,!=;
赋值运算符:=,+=,-=,*=,/=,%=,&=,|=,^=,<<=,>>=;
其他运算符:[],(),->,,(逗号运算符),new,delete,new[],delete[],->*。
不能重载的运算符只有5个:
类属关系运算符“.”,成员指针运算符“*”,作用域分辨符“::”,sizeof运算符和三目运算符“?:”。
(2)重载之后运算符的优先级和结合性都不变。
(3)四个“不能改变”
·不能改变运算符操作数的个数;
·不能改变运算符原有的优先级;
·不能改变运算符原有的结合性;
·不能改变运算符原有的语法结构。
(4)至少要有一个操作对象是自定义类型。
(5)重载的运算符含义必须清楚,不能有二义性。
(6)、必须重载为成员函数的运算符: [], (), –>, =
(7)、在类成员函数中重载运算符是不允许返回引用的,会出现“返回局部变量的地址”警告
(8)、cout << f1 << f2;
//用重载运算符表示,只能通过友员来实现
//如果要用成员函数,则会有cout.operator<<(const F& f),所以这是不
// 可能的.因此只能用友员来实现,operator<<(cout,f)
// 而cout是ostream型的,因此有以下标准格式.注意不能加const,因为
//cout是要改变的,会改变里的缓冲成员.
ostream& operator<<( /* 不能加const */ ostream& cout, constF&) //输出运算符的标准重载格式.
friend istream& operator>>(istream& is, F& f){ }//输入运算符重载标准格式
四.重载运算符的二种方法
1运算符是类成员函数
要实现操作符重载就要使用操作符重载函数,操作符重载函数用关键字operator实现,其形式为:返回类型 operator 操作符 (参数列表){}。操作符重载函数是一个函数,只不过这个函数的函数名为operator再加上后面要重载的操作符而已,比如要重载+号,则: hyong operator +(hyong m){}这就声明了一个返回类型为hyong的操作符函数,其函数名为operator +
class CTest
{
int i;
CTest operator +(int i)
{
CTest m_test=*this;
m_test.i =this->i+i;
return m_test;
}
}
那么调用时就可以这样:
Ctest m_test1,m_test2;
m_test2=m_test1+1; 也可以这样调用 m_test2=m_test1.operator(1);
2运算符是类的友元函数
Class CTest
{
Friend CTest operator+(CTest TA,CTest TB);
public:
CTest()
{
i=2;
}
public:
int i;
}
CTest operator+(CTest TA,CTest TB)
{
CTest TC
TC.i= TA.i+TB.i
return TC;
}
int main()
{
CTest a,b,c
c=a+b;
}
参数个数的限定
非成员函数:
单目运算符:参数表中只有一个参数;
双目运算符:参数表中只有两个参数
成员函数:
单目运算符:参数表中没有参数;
双目运算符:参数表中只有一个参数
重载运算符为成员函数后,当调用该运算符时,左操作数必须是该类的实例。友元函数中流参数定义第一个参数.才能调用cout<<obj;而成员函数流参数不是第一个参数,调用时应该是obj<<cout;(加入允许重载为成员函数的话)
虽然不能“重载”为成员函数,但是可以定义为新的成员函数,只不过使用习惯和常例不符而已。看下面的代码:
class test{
public:
ostream& operator<<(test& a);
test(){ name = 1;}
private:
int name;
};
ostream& test::operator<<(test& a)
{
cout<<a.name<<endl;
}
int main(int argc, char* argv[])
{
test *t = new test();
(*t)<<(*t);
system("pause");
exit(0);
}
3.作为类的成员和友元或者独立于类的区别
当操作符重载函数作为类的成员函数时,操作符重载函数的参数会比作为友元或者独立于类的操作符重载函数少一个参数,因为操作符重载类成员函数把调用该函数的第一个类的对象作为函数的第一个参数,也就是隐含的this指针指向调用该函数的第一个对象,所以会少一个参数。
4.调用操作符重载函数的方式:
4.1 调用类中的操作符重载函数的方法:当调用类中定义的操作符重载函数时最左边的对象是调用操作符重载函数的对象。比如在类hyong中重定义的+操作符 hyong operator +(hyong m){},有类hyong的对象m和n则调用操作符重载函数的方法有m+n和m.operator +(n),前一条语句会自动转换为后面这条语句,且m+n的表达式中最左边的对象是调用操作符重载函数的对象,而最右边的那个将被作为参数传送。也就是说 n+m会转换成n.operator +(m)。要记住当调用类中定义的操作符重载函数时最左边的对象是调用操作符重载函数的对象。
4.2 调用友元或独立的操作符重载函数的方法:当调用类的友元操作符重载函数或独立的操作符函数时语句m+n会转换为显示的调用方式,比如有友元或独立操作符重 载函数hyong operator +(hyong a, hyong b){}则当出现m+n时会转换成语句operator +(m, n)表达式的第一个对象传给第一个参数,第二个对象传给第二个参数。
5.需把其作为类的友元或者类的成员
一般来说操作符重载函数一般不要求作为类的成员函数或者是友元函数,一般情况下可以将操作符重载函数作为类的成员函数。但是有一种情况必须要求操作符函数 作为类的友元函数或者是独立的函数,就是一个内置类型和对象相加的情况。比如有语句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)这样就是正确的。当然如果这个操作符重载函数需要访问类中的私有成员时,就应把该函数定义为类的友元函数,如果不需要访问类中的私有成员,则可以定义 为友元也可以定义为独立函数。
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){}。