本文共 2809 字,大约阅读时间需要 9 分钟。
重载运算符是C++中一个强大特性,它允许我们自定义类的运算行为。通过重载运算符,我们可以为用户定义的类增加和内置类型相同的操作符功能,从而使其更加灵活和可扩展。
重载运算符的定义方式有以下两种:
通过 operator 关键字定义:
例如,定义一个加法运算符可以这样写:int operator+(const MyObject& a, const MyObject& b) { return a + b;}
直接定义:
有时候,如果运算符已经是成员函数,且参数较少,可以直接用+
的符号来定义运算符。例如:MyObject operator+(const MyObject& a) { return new MyObject(a.getValue());}
调用重载运算符的方式与普通运算符相同,但要明确表达我们是调用用户定义的重载版本:
例如:int data1 = 5; int data2 = 7; int sum = data1 + data2; // 调用默认的整数加法运算符 int sum = operator+(data1, data2); // �amakely 调用自定义重载的加法运算符
判断一个运算符是否是成员函数,可以通过以下规则:
=
)、下标运算符 [...]
、函数调用运算符 ()
和 成员访问运算符 (->
) 必须是成员函数。=
的复合赋值运算符(例如 +=
, -=
等)通常也应该定义为成员函数。bool operator==(const MyObject& a, const MyObject& b);
这种运算符不需要是成员函数。
因此,在定义运算符时,要根据具体需求决定是否将其定义为成员函数。
可选运算符 | 不能重载的运算符 |
---|---|
+ , - , * , / , % , ^ | :: , .* , . , ? : |
& , , , ~ , ! , = , ,= | , , ~ , ! , - |
< , > , <= , >= , ++ , -- | |
<< , >> , == , != , && , || | |
+= , -=', /=, %=, ^=, &=, *=` | |
[] (下标运算符) | |
-> (成员访问运算符), - , new , delete | |
括号 (), 和逗号 , |
注意:某些特殊运算符不允许重载,例如 ::
(标量的成员访问)、.*
(指向成员的指针下标)、? :
(选择表达式中的 :
)。
输入和输出运算符有一些特别的规则:
输出运算符 (<<
):
std::ostream& operator<<(const MyObject& obj) { obj.print(); return std::cout;}
输入运算符 (>>
):
MyObject operator>>(std::istream& is, MyObject& obj) { is >> obj.value; return obj;}
输入运算符的第一个参数通常是输入流的引用,第二个参数是目标对象的非常量引用。
在定义算术和关系运算符时,需要注意以下几点:
+=
),通常应优先使用复合赋值运算符,因为它比直接赋值更灵活。如果类包含相等性(==
),则通常也需要定义不等式运算符(!=
),反之亦然。确保相等运算符具有传递性,避免循环依赖。
递增和递减运算符通常是成员函数,定义方式如下:
前置递增运算符:
MyObject& operator++() { this->counter++; return *this;}
后置递增运算符:
由于与内置运算符保持一致,后置运算符需要接受一个额外的int
形参(通常不使用):MyObject operator++(int) { // 这里通常无需改变逻辑,建议保持可选性。 return *this;}
同样,递减运算符 (--
) 的定义方式与递增类似。
成员访问运算符通常被定义为成员函数。例如:
解引用运算符 ->
:
MyObject* operator->() { return *this;}
箭头运算符 -&>
常用于subtotal 类:
MyObject operator->(const MyObject& rhs) { return *this / rhs;}
解引用和乘法运算符的区别在于,解引用是一个一元运算符,而乘法是一个二元运算符。
函数调用运算符可以像普通函数一样调用,具有类功能:
定义函数调用运算符的方式:
void operator()() { doSomething();}
好处是可以将对象当作函数处理。
如果类同时定义多个版本的调用运算符,其参数类型或数量应有所不同,以避免歧义。
C++ 提供了一些标准库定义的函数对象,这些可以用来简化算法编写。例如:
算术函数对象:
std::plus plus;int result = std::accumulate(std::begin(list), std::end(list), 0, plus);
关系函数对象:
std::greater greater;if (std::every_of(greater, begin(list), end(list))) { // 做一些判断}
这些函数对象可以用来处理自定义类中的算术和关系运算。
类型转换运算符是成员函数,其名称为 operator type()
。它们用于将类的对象转换为目标类型,通常取名为 toType
或者 `type().
在实现运算符时,需要注意性能和错误处理:
this
,除非必要。通过遵循这些规则,我们可以创建一个更加灵活和可靠的类框架。
重载运算符是C++强大功能的体现,它允许我们为类定义一系列自定义的运算符行为。通过理解和遵循上述规则,我们可以更好地利用重载运算符,避免潜在的问题,从而提高代码质量和可维护性。
转载地址:http://yptqz.baihongyu.com/