C++中预定义的运算符其运算对象只能是基本数据类型,而不适用于用户自定义类型(如类).
// 同上,内置的运算符 只能应用于内置的数据类型 ...比如 int char double .等等。
(一) C++不允许用户自己定义新的运算符,只能对已有的C++运算符进行重载。
// 就是说只能重载内置的 + - * / 等运算符,不能自己创造运算符计算。 。
(二) C++允许重载的运算符C++中绝大部分的运算符允许重载.
不能重载的运算符只有5个:
(1) 成员访问运算符.
(2) 作用域运算符∷
(3) 条件运算符?:
(4) 成员指针运算符*
(5) 编译预处理命令的开始符号#
(三) 重载不能改变运算符运算对象(即操作数)的个数。
// 不能改变运算符运算对象, 比如+法运算符,那么它有两个操作数 ..当我们重载它的时候 也只能有两个操作数 。
(四) 重载不能改变运算符的优先级别。
// 重载完之后并不能改变它的优先级别,比如 +号, 无论你怎么设计重载函数. 它永远不可能比()的优先级高......
(五) 重载运算符的函数不能有默认的参数,否则就改变了运算符参数的个数,与前面第(3)点矛盾。
// 于上面3..同。
(六) 重载的运算符必须和用户定义的自定义类型的对象一起使用,其参数至少应有一个是类对象(或类对象的引用)。也就是说,参数不能全部是C++的标准类型,以防止用户修改用于标准类型数据的运算符的性质。
// 重载的参数不能全部是C++内置数据类型。 至少要有一个是自定义类型。因为如果我们定义的是两个内置的类型 就会跟系统所定义的冲突。 因为当我们使用内置的运算符时,那么编译器其实也是调用的一个重载运算符进行计算。这是编译器自动添加的。 如果我们也定义的相同 那么肯定会产生冲突。
(七) 用于类对象的运算符一般必须重载,但有两个例外,运算符“=”和“&”不必用户重载。
① 赋值运算符(=)可以用于每一个类对象,可以利用它在同类对象之间相互赋值。
② 地址运算符&也不必重载,它能返回类对象在内存中的起始地址。
// 前面已经说过,C++内置运算符只能计算内置的数据类型 。所以当我们要使用自定义类型时 就必须要进行重载..
总之,当C++语言原有的一个运算符被重载之后,它原先所具有的语义并没有消失,只相当于针对一个特定的类定义了一个新的运算符。
运算符重载可以使用成员函数和友元函数两种形式。可以参考以下的经验:
(1)只能使用成员函数重载的运算符有:=、()、[]、->、new、delete。
(2)单目运算符最好重载为成员函数。
(3) 对于复合的赋值运算符如+=、-=、*=、/=、&=、!=、~=、%=、>>=、<<=建议重载为成员函数。
(4) 对于其它运算符,建议重载为友元函数。
运算符重载的方法是定义一个重载运算符的函数,在需要执行被重载的运算符时,系统就自动调用该函数,以实现相应的运算。也就是说,运算符重载是通过定义函数实现的。运算符重载实质上是函数的重载。重载运算符的函数一般格式如下:
函数类型 operator 运算符名称 (形参表列)
{
对运算符的重载处理
}
重载为类成员函数时参数个数=原操作数个数-1
(后置++、--除外)
// 当重载为类成员函数时,参数个数等于原来的操作数-1 ..比如 对象a +对象b ..我们重载的时候需要两个操作数 a 和b 但我们传递过去一个就可以了 , 比如 a+b 我们只需要把b传递过去就可以了。因为当调用重载运算符时 就是a调用的重载运算符,那么它就是当前对象 它就是这时的this 指针 ..而且类成员函数只能使用两个类中成员...
重载为友元函数时 参数个数=原操作数个数,且至少应该有一个自定义类型的形参。
//与上面没多大区别,但它却可以调用非类中对象.. 比如调用一个对象a+1 ..注意的是即使定义为友元函数,它的操作数也必须有一个为自定义类型。
看一个实例:
#include
using namespace std;
class complex //复数类声明
{
public: //外部接口
complex(double r=0.0,double i=0.0)
{
real=r;
imag=i;
} //构造函数
complex operator + (complex c2); //+重载为成员函数
complex operator - (complex c2); //-重载为成员函数
void display(); //输出显示复数
private: //私有数据成员
double real; //复数实部
double imag; //复数虚部
};
complex complex::operator +(complex c2) //重载函数实现
{
complex c;
c.real=real+c2.real;
c.imag=imag+c2.imag;
return complex(c.real,c.imag);
}
complex complex::operator -(complex c2) //重载函数实现
{
complex c;
c.real=real-c2.real;
c.imag=imag-c2.imag;
return complex(c.real,c.imag);
}
void complex::display()
{ cout<<"("<
int main() //主函数
{
complex c1(5,4),c2(2,10),c3; //声明复数类的对象
cout<<"c1="; c1.display();
cout<<"c2="; c2.display();
c3=c1-c2; //使用重载运算符完成复数减法
cout<<"c3=c1-c2=";
c3.display();
c3=c1+c2; //使用重载运算符完成复数加法
cout<<"c3=c1+c2=";
c3.display();
system("pause");
return 0;
}
程序输出的结果为:
c1=(5,4i)
c2=(2,10i)
c3=c1-c2=(3,-6i)
c3=c1+c2=(7,14i)
通过代码我们可以看出: 定义了两个成员函数重载运算符..重载了+ 和- . 当我们使用这个类的两个成员进行相加的或者相减的时候就会自动调用重载的运算符..使用我们在重载的运算符中所定义的操作。那我们可以看到,在进行+或者-的时候是把两个对象中保存的复数的值进行加减 然后返回了。 要注意的是并不是+号和减号被完全改变了,而只是这个类中的对象在进行+ -操作的时候才会调用重载.
我们来测试一下; 我们在main()函数中再定义三个变量 ,int a=5,b=3,c; c=a-b ; 然后再输出c的值 ,我们发现输出为2 . .这也证明了我们所定义的重载运算符并没有改变它原来的功能..而是赋予了它多重的含义..
那我们再来看下运算符重载在友元函数中的使用。
我们只需要将complex complex::operator +(complex c2) //重载函数实现
{
complex c;
c.real=real+c2.real; // real 代表 this->real 其实就是代表传递进来的当前对象.
c.imag=imag+c2.imag;
return complex(c.real,c.imag);
}
这段代码 修改一下... 改为 complex friend complex::operator +(complex c2 complex c3)
那么同样也可以完成相同的功能..而且还更容易扩充..因为从上面得知..重载的运算符必须和用户定义的自定义类型的对象一起使用. 也就是说至少有一个自定义类型..或者是它的引用..如果我们使用成员运算符重载的话只能使用类中的对象成员..而使用友元运算符重载那么我们则可以使用类外的数据..当我们需要使用的时候直接修改为 complex friend complex::operator +(complex c2 int a) 如这样的形式就可以了。
[C++]重载运算符 收藏
所谓重载,就是重新赋予新的含义。函数重载就是对一个已有的函数赋予新的含义,使之实现新功能。
运算符也可以重载
运算符重载是对已有的运算符赋予多重含义
必要性
C++中预定义的运算符其运算对象只能是基本数据类型,而不适用于用户自定义类型(如类)
(一) C++不允许用户自己定义新的运算符,只能对已有的C++运算符进行重载。
(二) C++允许重载的运算符C++中绝大部分的运算符允许重载.
不能重载的运算符只有5个:
(1) 成员访问运算符.
(2) 作用域运算符∷
(3) 条件运算符?:
(4) 成员指针运算符*
(5) 编译预处理命令的开始符号#
(三) 重载不能改变运算符运算对象(即操作数)的个数。
(四) 重载不能改变运算符的优先级别。
(五) 重载运算符的函数不能有默认的参数,否则就改变了运算符参数的个数,与前面第(3)点矛盾。
(六) 重载的运算符必须和用户定义的自定义类型的对象一起使用,其参数至少应有一个是类对象(或类对象的引用)。也就是说,参数不能全部是C++的标准类型,以防止用户修改用于标准类型数据的运算符的性质。
(七) 用于类对象的运算符一般必须重载,但有两个例外,运算符“=”和“&”不必用户重载。
① 赋值运算符(=)可以用于每一个类对象,可以利用它在同类对象之间相互赋值。
② 地址运算符&也不必重载,它能返回类对象在内存中的起始地址。
总之,当C++语言原有的一个运算符被重载之后,它原先所具有的语义并没有消失,只相当于针对一个特定的类定义了一个新的运算符。
运算符重载可以使用成员函数和友元函数两种形式。可以参考以下的经验:
(1)只能使用成员函数重载的运算符有:=、()、[]、->、new、delete。
(2)单目运算符最好重载为成员函数。
(3) 对于复合的赋值运算符如+=、-=、*=、/=、&=、!=、~=、%=、>>=、<<=建议重载为成员函数。
(4) 对于其它运算符,建议重载为友元函数。
运算符重载的方法是定义一个重载运算符的函数,在需要执行被重载的运算符时,系统就自动调用该函数,以实现相应的运算。也就是说,运算符重载是通过定义函数实现的。运算符重载实质上是函数的重载。重载运算符的函数一般格式如下:
函数类型 operator 运算符名称 (形参表列)
{
对运算符的重载处理
}
重载为类成员函数时参数个数=原操作数个数-1
(后置++、--除外)
重载为友元函数时 参数个数=原操作数个数,且至少应该有一个自定义类型的形参。
将“+”、“-”运算重载为复数类的成员函数。
规则:
实部和虚部分别相加减。
操作数:
两个操作数都是复数类的对象。
#include
using namespace std;
class complex //复数类声明
{
public: //外部接口
complex(double r=0.0,double i=0.0)
{
real=r;
imag=i;
} //构造函数
complex operator + (complex c2); //+重载为成员函数
complex operator - (complex c2); //-重载为成员函数
void display(); //输出显示复数
private: //私有数据成员
double real; //复数实部
double imag; //复数虚部
};
complex complex::operator +(complex c2) //重载函数实现
{
complex c;
c.real=real+c2.real;
c.imag=imag+c2.imag;
return complex(c.real,c.imag);
}
complex complex::operator -(complex c2) //重载函数实现
{
complex c;
c.real=real-c2.real;
c.imag=imag-c2.imag;
return complex(c.real,c.imag);
}
void complex::display()
{ cout<<"("<
{ complex c1(5,4),c2(2,10),c3; //声明复数类的对象
cout<<"c1="; c1.display();
cout<<"c2="; c2.display();
c3=c1-c2; //使用重载运算符完成复数减法
cout<<"c3=c1-c2=";
c3.display();
c3=c1+c2; //使用重载运算符完成复数加法
cout<<"c3=c1+c2=";
c3.display();
}
程序输出的结果为:
c1=(5,4i)
c2=(2,10i)
c3=c1-c2=(3,-6i)
c3=c1+c2=(7,14i)
在本程序中对运算符“+”,”-”进行了重载,使之能用于两个复数的相加减。在该例中运算符重载函数operator+ ,operator-作为Complex类中的成员函数。
“+” ,”-”是双目运算符,为什么在程序中的重载函数中只有一个参数呢?实际上,运算符重载函数有两个参数,由于重载函数是Complex类中的成员函数,有一个参数是隐含的,运算符函数是用this指针隐式地访问类对象的成员。
可以看到,重载函数operator+访问了两个对象中的成员,一个是this指针指向的对象中的成员,一个是形参对象中的成员。如this->real+c2.real,this->real就是c1.real。
在将运算符函数重载为成员函数后,如果出现含该运算符的表达式,如c1+c2,编译系统把它解释为c1.operator+(c2)
即通过对象c1调用运算符重载函数,并以表达式中第二个参数(运算符右侧的类对象c2)作为函数实参。运算符重载函数的返回值是Complex类型,返回值是复数c1和c2之和(Complex(c1.real + c2.real,c1.imag+c2.imag))。