博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

C++ Primer 读书笔记 Charpter 14 重载操作符和转换

Posted on 2010-08-21 01:25  KurtWang  阅读(354)  评论(0编辑  收藏  举报
  1. 重载操作符必须具有一个类类型操作数:int operator+(int,int)是非法的
    1. ||和&&不具备短路性质,重载||和&&不是好做法
    2. 重载函数可以是成员函数(形参少一个,隐含的this指针作为第一个操作数)和非成员函数。
      1. 赋值,下标,调用和成员访问箭头等操作符必须定义为成员
    3. 操作符重载可以设置为友元
    4. 不要重载具有内置含义的操作符,例如逗号,取地址,逻辑与,逻辑或等
  2. 重载操作符
    1. 为了和内置操作符保持一致,加法返回一个右值
    2. // assumes that both objects refer to the same isbn
      Sales_item operator+(const Sales_item& lhs, const Sales_item& rhs)
      {
      	Sales_item ret(lhs); // copy lhs into a local object that we'll return
      	ret += rhs; // add in the contents of rhs
      	return ret; // return ret by value
      }
    3. 重载箭头操作符必须返回指向类类型的指针或者返回定义了自己的箭头操作符的类类型对象,p->display()等于(p.operator->())->display
    4. IO 操作符必须为非成员函数
    5. 赋值必须返回对 *this 的引用
    6. 同时定义前缀式操作符和后缀式操作符存在一个问题:它们的形参数目和类型相同,普通重载不能区别所定义的前缀式操作符还是后缀式操作符。
      1. 为了解决这一问题,后缀式操作符函数接受一个额外的(即,无用的)int 型形参。使用后缀式操作符进,编译器提供 0 作为这个形参的实参。尽管我们的前缀式操作符函数可以使用这个额外的形参,但通常不应该这样做。那个形参不是后缀式操作符的正常工作所需要的,它的唯一目的是使后缀函数与前缀函数区别开来。
      2. // 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;
        }
        
        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
        }
  3. 函数对象:经常用作通用算法的实参。重载了 operator()(即,函数调用操作符)的类的对象,称为“函数对象”。这种对象通常用于定义与标准算法结合使用的谓词函数。
      // determine whether a length of a given word is longer than a stored bound
      class GT_cls {
      public:
      	GT_cls(size_t val = 0): bound(val) { }
      	bool operator()(const string &s)
      	{ return s.size() >= bound; }
      private:
      	std::string::size_type bound;
      };
      
      cout << count_if(words.begin(), words.end(), GT_cls(6))
      << " words 6 characters or longer" << endl;
    1. 标准库定义的函数对象
    2. plus<Type> applies +
      minus<Type> applies -

      等等

    3. 标准库提供了一组函数适配器,用于特化和扩展一元和二元函数对象。函数适配器分为如下两类:
      1. Binders: 绑定器,是一种函数适配器,它通过将一个操作数绑定到给定值而将二元函数对象转换为一元函数对象。count_if(vec.begin(), vec.end(), bind2nd(less_equal<int>(), 10));
    4. 2. Negators: 求反器,是一种函数适配器,它将谓词函数对象的真值求反。count_if(vec.begin(), vec.end(), not1(bind2nd(less_equal<int>(), 10)));
  4. 转换操作符
    1. 类可以定义转换,当一个类型的对象用在需要另一不同类型对象的地方时,自动应用这些转换。接受单个形参且未指定为explicit的构造函数定义了从其他类型到类类型的转换。
    2. 重载操作符转换函数则定义了从类类型到其他类型的转换。转换操作符必须为所转换类的成员,没有形参并且不定义返回值,转换操作符返回操作符所具有类型的值,例如,operator int() 返回 int。
    3. 像其他转换一样,编译器将自动应用这个转换。
    4. class SmallInt {
      public:
      	SmallInt(int i = 0): val(i)
      	{ 
              	if (i < 0 || i > 255)
      			throw std::out_of_range("Bad SmallInt initializer");
      	}
      	operator int() const { return val; }
      private:
      	std::size_t val;
      };
    5. 如果存在一个到 int 的转换,则以下代码:
      SmallInt si(3);
      si + 3.14159; // convert si to int, then convert to double
      可这样确定:
      1. 将 si 转换为 int 值。
      2. 将所得 int 结果转换为 double 值并与双精度字面值常量 3.14159 相加,得到 double 值。