有一个自定义类unsignedint表示无符号型的整数,
Unsignedint un1(1);
Unsignedint un2(1);
un1 += un2; // un1+un2,也就是一加一
如果不重载+=的话将会出错,那么要使用在的话该怎么定义呢
UnsignedInt& operator += (const UnsignedInt& other)
其实上面的实际表达的意思就是一加一,其实我们可以这样写来实现自增
un1 ++; 或 ++un1;
那么让其自增操作是怎么定义呢?
前置式:UnsignedInt& operator++ ()
后置式:const UnsignedInt& operator++ (int)
同样自减操作符定义如下:
前置式:UnsignedInt& operator-- ()
后置式:const UnsignedInt& operator-- (int)
你可能会发现一个问题,相对于+=运算来说,自增或自减都没有第二个操作数,实际的表现就是没有参数,但我们知道重载函数系以其参数型别来区分彼此,也就是说前置或后置是根本无法区分的。为了弥补这个语言上的不足,只好让后置式有一个 int型的自变量,并且他被调用时,编译器默认的将该int指定为0值。
我们再来看一下它的实现:
UnsignedInt& operator++ ()
{
this->un += 1;
return *this;
}
const UnsignedInt& operator++ (int)
{
UnsignedInt OldValue = *this;
++(*this); //调用前置式
return OldValue;
}
是的,正如我们所看到的,参数的唯一目的只是为了区分前置式还是后置式,实际上它并没有被用到。如果指定了int的变量的名称, 比如int n,那么编译器就可能给出警告,这样的话就让人感觉不舒服,尽管他是正确的。与其这样还不如略去实际的变量声明,直接就写类型就行了。
你可能会发现前置和后置还有一个区别:后置式多了一个const修饰符,可这是为什么呢?考虑如下代码:
UnsignedInt un1(1);
un1++++;
若没有const修饰符un1的值等于多少?答案是2。为什么呢?un1++++可以理解为如下的各式:
(un1++) ++ à un1.operator++(0). operator++(0);
由于un1++返回的结果是一个临时值,在临时值的基础上进行的后置操作只是让临时值增加1,而Un1被使用了一次而且只增加了1,这违背了这样的两次连续操作要达到un1加2的目的。
所以const修饰符用于限定进行第二次连续操作的执行,保证代码执行逻辑的正确性。因此只要出现连续加的情况,编译器就会报错,从编译期就指出错误,而不至于将这样的错误延续到执行期进行人工的排除。
而对于前置式的累加(减)操作则式完全合法的。比如:++++un1的结果等于3。
最后探讨一下效率问题。你认为那个效率更高呢?答案是前置式!可这是为什么呢?正如我们前面所看的后置式的实现过程那样,后置式在其实现过程中引入了局部变量,而局部的构造和析构都有需要浪费一定的时间成本。所以前置式的效率要高于后置式。
实现代码:
class UnsignedInt
{
unsigned int un;
public:
UnsignedInt():un(0){};
UnsignedInt(int n){ un = n; }
~UnsignedInt() {};
UnsignedInt& operator++ ()
{
this->un += 1;
return *this;
}
const UnsignedInt& operator++ (int n)
{
UnsignedInt OldValue = *this;
++(*this);
return OldValue;
}
UnsignedInt& operator = (const UnsignedInt& other)
{
this->un = other.un;
return *this;
}
};