在进行类的设计时,可能会经常遇到运算符重载的情况,常见的运算符重载格式为:
返回类型 operator 运算符 (parameter);
还有一些的格式为:
operator double() const; // 以重载double为例
在运算符重载的时候应该注意,一定要让重载后的运算符与系统定义的保持特性上的基本一致,不能使其偏离基本含义,基本特性。你可以重载除了
. .* :: ?: new delete sizeof typeid以外的所有运算符。
运算符可以以成员函数、友元函数、全局函数形式进行重载,下面说一下前缀、后缀运算符的区别,以重载运算符为成员函数为例进行说明.
class BaseClass
{
public:
// 前缀、后缀以int 型参数决定
BaseClass& operator++ (); // 前缀
const BaseClass operator++ (int); // 后缀
BaseClass& operator-- (); // 前缀
const BaseClass operator-- (int); // 后缀
private:
int number;
};
BaseClass& operator++ () // 前缀
{
*this.number += 1;
return *this;
}
const BaseClass operator++ (int) // 后缀
{
BaseClass oldObject = *this;
++ *this; // 调用operator ++ ()
return oldObject;
}
……
这里,前缀返回一个引用,后缀返回一个const 对象,对于前缀运算来说,我们应该允许其进行如下形式的运算:
k = ++i + j;
如果我们返回的是一个const 类型的话,就会禁止这种运算(operator + ()不会被重载为 const成员函数, 所以如果返回一个const 引用,就会禁止这种运算—const对象无法调用非const函数),这部是我们所希望的。
而后缀运算符则需要禁止如 i++++这类运算,原因有2。
第一,内置的int 类型禁止这种运算,这种运算是非法的,我们应该跟内置类型保持一致。
第二,其结果是与我们的期望不一致的。我们期望其结果为对i进行两次加运算,但结果事与愿违。当我们使用i++++时,其被解析成i.operator++(0).operator++(0);当第一次使用,第一次调用后缀运算,将i进行加操作,返回一个临时对象,第二次,“对临时对象加1操作”,也就是i只进行了一次加1操作!和我们的直觉有着如此巨大的差异,我们应该避免这种事情的发生,它会迷惑我们,况且这么做本不那么合法,所以我们应该避免这种情况发生,而我们只需要加上一个const,如此简单。
从以上的代码可以知道,在C++中,前缀的效率要高于后缀的效率,以为后缀运算包括了临时对象的构造和析构,所以在C++中应该尽量使用前缀,除非确实需要再使用后缀(当然,在C中部存在这种问题,编译器对C代码进行汇编转换的时候可以使得两者的效率相同,只是代码执行顺序不同而已)。
接着说一下&& || , 三种运算符,原则上不要重载这三个运算符,因为&&和||会进行类似短路的操作,而你重载后市无论如何都达不到这种效果的,无论如何都达不到。对于逗号操作符,你无法模仿它的特性,你无法让左边的操作先于右边的进行,因为无论是标准还是编译器都没有规定必须左先于右。
所以,明智的做法是不要重载 “&& || , ”三种运算符。
最后想说一下,如果要重载的几个运算符之间有一定的联系,可以互相利用,那么你只需要重载其中的一部分,其它的用这些进行编写,那么你无论是编写,还是维护,都只需要做其中的一部分事情,而不是全部。例如,如果需要同时重载operator += 和 operator + 以方便计算,那么你就可以这么做
BaseClass& operator += (const BaseClass& rhs);
const BaseClass operator + (const BaseClass& lhs, const BaseClass& rhs)
{
return BaseClass(lhs) += rhs; // 返回一个临时对象会允许编译器优化,可能提高效
//率
}