C++重载运算符
重载运算符不会改变运算符的优先级,也无法改变运算符的运算对象数。
重载某个类的某个运算符就是写一个函数定义这个类中的这个运算符。声明函数:qxz operator + (qxz b);
。这个函数可以是全局的,也可以是成员函数。如果是全局的,那么参数从左到右应该和运算符的运算对象相同;如果是成员函数,系统默认最左边的运算对象为第一个参数this
,因此形参表里的参数要少一个。由于外部需要调用重载了的运算符,因此这个成员函数必须在public
内。如果重载运算符不改变参数、不改变成员,那么参数和函数都应当声明为const
。由于重载的运算符经常要访问类的私有成员,因此一般会把这个函数设为类的友元函数。
赋值运算符。任何类的对象本身就可以通过=
赋值,这是因为编译器为每个类都生成了一个默认的等号重载函数。因此我们讨论的赋值运算符的重载是一种新的重载方式。C++要求=
的重载必须是成员函数。由于C++中赋值是个运算,这个运算本身是有返回值的,因此我们在函数中一般把操作作用在*this
上,然后返回*this
。因此函数的返回值是这个类的引用类型。声明:qxz &operator = (const qxz &b){ return *this; }
下标运算符。C++中的下标运算符是一个二元运算符,例如a[i]
中a
是第一个运算对象,i
是第二个运算对象。C++要求[]
的重载必须是成员函数。这个运算符的返回值应当是一个引用类型,这样就可以就可以方便地进行赋值等操作。声明:qxz &operator[](int &i);
函数调用运算符。C++中()
是一个二元运算符,第一个运算对象是函数名,第二个运算对象是后面的参数表。声明:A operator()(...);
++
和--
的重载。由于这两个一元运算符既可以作为前缀又可以作为后缀,而他们对应的重载函数是完全一样的。为了解决这个问题,C++编译器规定后缀运算符重载函数接受一个额外的int
型的参数。因此,前缀的重载声明qxz &operator++(){}
,后缀的重载声明qxz &operator++(int x){}
。
输入输出运算符的重载。<<
是一个二元运算符,一个是ostream
的一个对象,一个是要输出的对象。输入输出运算赋的重载写作全局函数,这样声明:ostream &operator<< (ostream &os, const ClassType &obj){ os << ...; return os;}
。>>
也是相似的,这样声明:istream &operator(istream &is, ClassType & obj){ is >> ..; return is; }
(注意第二个参数不用const
,因为输入是改变这个参数的,并且注意到我们用了引用类型没能)
我们可以禁止内置类型到类类型的隐式转换,方法是在构造函数前加一个关键词explicit
,并且让编译器报错。explicit qxz(int a){ alarm = a; }
。除非有明显地需要隐式转换的理由,否则一般都应当把构造函数设定为explicit
。
我们可以写一个类型转换函数来将自定义的类类型转化为指定的类型。格式为(以int
为例)operator int() const { return ...; }
。通过这样的转换,一定程度上能够减少需要重载的运算符的个数。