重载操做符与转换

[0. 必须定义为类成员的操做符]ios

赋值 =;
下标 [];
调用 ();
成员访问箭头 ->;算法

 

[1. 输入和输出操做符]数组

支持 I/O 操做的类所提供的 I/O 操做接口,
通常应该与标准库 iostream 为内置类型定义的接口相同,
所以,许多类都须要重载输入和输出操做符。函数

为了与 IO 标准库一致,操做符应接受 ostream& 做为第一个形参,
对类类型 const 对象的引用做为第二个形参,并返回对 ostream 形参的引用。post

重载输出操做符通常的简单定义以下:this

// general skeleton of the overloaded output operator
ostream&
operator <<(ostream& os, const ClassType &object)
{
// any special logic to prepare object

// actual output of members
os << // ...

// return ostream object
return os;
}


重载 "->" 必须返回指向类类型的指针,或者返回定义了本身的"->"的类类型对象。spa


[2. 定义自增/自减操做符]指针

C++ 语言不要求自增操做符或自减操做符必定做为类的成员,
可是,由于这些操做符改变操做对象的状态,因此更倾向于将它们做为成员。code


在为类定义重载的自增操做符和自减操做符以前,
还必须考虑为咱们本身的类定义自增操做符和自减操做符的前缀和后缀操做符。对象

前缀式操做符的声明,举例以下:

class CheckedPtr {
public:
  CheckedPtr& operator++(); // prefix operators
  CheckedPtr& operator--();
  // other members as before
};

为了与内置类型一致,前缀式操做符应返回被增量或减量对象的引用。

这个自增操做符根据 end 检查 curr,从而确保用户不能将 curr 增量到超过数组的末端。
若是 curr 增量到超过 end,就抛出一个 out_of_range 异常;
不然,将 curr 加 1 并返回对象引用(自减操做符的行为与此相似):

// prefix: return reference to incremented/decremented object
CheckedPtr& CheckedPtr::operator++()
{
  if (curr == end)
    throw out_of_range
        ("increment past the end of CheckedPtr");
  ++curr; // advance current state
  return *this;
}

 

区别操做符的前缀和后缀形式

同时定义前缀式操做符和后缀式操做符存在一个问题:
它们的形参数目和类型相同,普通重载不能区别所定义的前缀式操做符仍是后缀式操做符。

为了解决这一问题,后缀式操做符函数接受一个额外的(即,无用的)int 型形参。
使用后缀式操做符进,编译器提供 0 做为这个形参的实参。
尽管咱们的前缀式操做符函数可使用这个额外的形参,但一般不该该这样作。
那个形参不是后缀式操做符的正常工做所须要的,它的惟一目的是使后缀函数与前缀函数区别开来。


接上面的例子,后缀式操做符以下:

class CheckedPtr {
public:
  // increment and decrement
  CheckedPtr operator++(int); // postfix operators
  CheckedPtr operator--(int);
  // other members as before
};

为了与内置操做符一致,后缀式操做符应返回旧值(即,还没有自增或自减的值),
而且,应做为值返回,而不是返回引用。

后缀式操做符能够这样实现(后缀自减与此相似):

// postfix: increment/decrement object but return unchanged value
CheckedPtr CheckedPtr::operator++(int)
{
  // no check needed here, the call to prefix increment will do the check
  CheckedPtr ret(*this); // save current value
  ++*this; // advance one element, checking the increment
  return ret; // return saved state
}

操做符的后缀式比前缀式复杂一点,必须记住对象在 +1 或 -1 以前的状态。
这些操做符定义了一个局部 CheckedPtr 对象,
将它初始化为 *this 的副本,即 ret 是这个对象当前状态的副本。

// Question:
  讨论容许将空数组实参传给 CheckedPtr 构造函数的优缺点。
// Answer:
  
优势:构造函数的定义简单
  缺点:致使所构造的对象有可能没有指向有效的数组,从而失去其使用价值
  比较完善的作法是应该在构造函数中队参数检查。
// Question:
  为何没有定义自增和自减操做符的 const 版本?
// Answer:
  由于对 const 对象不能使用自增或自减操做。

 

[3. 类类型转换和标准转换]

使用转换函数时,被转换的类型没必要与所须要的类型彻底匹配。
必要时可在类类型转换以后跟上标准转换以得到想要的类型。

注意:

1) 可是,类类型转换以后不能再跟另外一个类类型转换。
  若是须要多个类类型转换,则代码将出错。

2) 既为算术类型提供转换函数,又为同一类类型提供重载操做符,
  可能会致使重载操做符和内置操做符之间的二义性。

经过定义内置操做符的重载版本,咱们能够为本身的类型(即,类类型或枚举类型)
的对象定义一样丰富的表达式集合。
重载操做符必须具备至少一个类类型或枚举类型的操做符。
应用于内置类型时,与对应操做符具备一样数目的操做数、一样的结合性和优先级。

大多数重载操做符能够定义为类成员或普通非成员函数,
赋值操做符、下标操做符、调用操做符和箭头操做符必须为类成员。
操做符定义为成员时,它是普通成员函数。
具体而言,成员操做符有一个隐式 this 指针,该指针必定是第一个操做数,
即,一元操做符惟一的操做数,二元操做符的左操做数。

重载了 operator()(即,函数调用操做符)的类的对象,称为“函数对象”。
这种对象一般用于定义与标准算法结合使用的谓词函数。

转换操做符必须为所转换类的成员,无形参而且不定义返回值,转换操做符返回操做符所具备类型的值。

相关文章
相关标签/搜索