设为首页 加入收藏

TOP

Effective C++读书笔记(条款24-29)(一)
2015-07-20 17:17:53 来源: 作者: 【 】 浏览:15
Tags:Effective 读书 笔记 条款 24-29

Effective C++第四篇,扩展的有点多...


(四).设计与声明

____________________________________________________________________________________________________________________________________

条款24:若所有参数皆需类型转换,请为此采用non-member函数

#1.如果你需要为某个函数的所有参数(包括被 this指针所指的那个隐喻参数)进行
类型转换,那么这个函数必须是个 non-member。
//假设有个有理数类:
class Rational{
public:
    Rational(int numrator=0, int denomination=1);
    int numerator()const;
    int denomination()const;
    ...
};
//如果operator*写成Rational成员函数的话:
class Rational{
public:
    ...
    const Rational operator*(const Rational& rhs)const;
    ...
};

Rational oneEigth(1,8);  //很好
Rational oneHalf(1,2);   //很好
Rational result = oneHalf * oneEighth;  //很好
result = result * oneEighth //很好

//当尝试混合运算时:
result = oneHalf*2;   //result = oneHalf.operator*(2);很好
result = 2*oneHalf;   //result = 2.operator*(oneHalf);出错,继续尝试non-member函数

//当编译器试图调用non-member函数 result = operator*(2, oneHalf);时
//依旧没有找到对应的non-member函数,因此最终导致出错。

//【所以我们应该实现一个这样的non-member函数】:
const Rational operator*(const Rational& lhs,const Rational& rhs)
{
    return Rational(lhs.numerator()*rhs.numerator(),
                lhs.denomination()*rhs.denomination());
}

#2.决定上述non-member函数是non-friend函数还是friend函数的理由是
“是否必须对class内部private成员或protected成员进行访问”,
若需要,则该non-member函数应是friend函数,
若不需要,为满足最大封装性原则,该non-member函数应是non-friend函数。
____________________________________________________________________________________________________________________________________
条款25:考虑写出一个不抛出异常的swap函数
#1.如果swap的缺省实现码对你的class或class template提供了可接受的效率,
请使用该缺省实现版:
namespace std{
    template
  
   
    void swap(T&a, T&b)        //std:swap的典型实现
    {                           //置换a和b的值
        T temp(a);
        a = b;
        b = temp;
    }
}
  
反之,如果因class或class template使用了pImp手法(pointer to implementation):
class WidgetImpl{
public:
    ...
private:
    int a, b, c;
    std::vector
  
    v;
    ...
};
class Widget{
public:
    Widget(const Widget& rhs);
    Widget& operator=(const Widget&rhs)
    {
        ...
        *pImv = *(rhs.pImpl);
        ...
    }
    ...
private:
    WidgetImpl* pImv;
};
  
从而引起了效率不足,请做以下几件事来提高效率:
(1).提供一个public swap member函数:
//pImv是private成员变量,所以要从内部来swap,
//当然也可用friend,但这样的写法和STL一致
class Widget{
public:
    ...
    void swap(Widget& other)
    {
        using std::swap;
        swap(pImpl, other.pImpl);
    }
    ...
};
//该swap函数保证了异常安全性和高效性,因为swap置换的是指针,对于指针
//和内置类型的置换操作绝不会抛出异常,并且还很高效。如果是对自定义类型
//执行swap函数,则会因为copy构造函数和copy assignment操作符而允许抛出异常。

(2).在你的class或template所在的namespace(如果没有,则是globe)内提供一个
non-member swap函数,并令它调用上述的swap函数,例如:
namespace WidgetStuff{
    ...
    template
  
   
    class Widget {...}
    ...
    template
   
     void swap(Widget
    
     & a, Widget
     
      & b) { a.swap(b); } }
     
    
   
  

(3).如果正在编写的是一个class(而非class template),为你的class特化std::swap,
并让它调用你的swap member函数,例如:
namespace std{
    template<>
    void swap
  
   (Widget& a, Widget& b)
    {
        a.swap(b);
    }
}
//=======================================================================
// 理由:
// 好处是即使客户不慎直接调用了std::swap,至少也能获得一个全特化版的swap函数,
// 另外,C++只运行class template偏特化,但不允许function template的偏特化,
// 因此无法通过编译(虽然某些编译器错误的接受了它)。
//=======================================================================
  

(4).如果你调用swap,请使用using声明式,以便让std::swap在函数中曝光可见,从
而在swap直接书写调用时可获得如下的效率查找:
<1>.在与class相同的 namespace 中查找swap函数。
<2>.在globe坏境中查找swap函数。
<3>.在namesapce std中查找全特化swap函数(如果是class而非template,并且予以了实现)
<4>.在namesapce std中查找一般swap函数。

#2.在std内进行std tem
首页 上一页 1 2 3 4 下一页 尾页 1/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇hdu 5014 贪心+位处理 下一篇POJ3169(最短路+差分约束)

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·如何理解c语言指针和 (2025-12-27 01:19:11)
·为什么C标准库没有链 (2025-12-27 01:19:08)
·玩转C语言和数据结构 (2025-12-27 01:19:05)
·MySQL 基础入门视频 (2025-12-26 23:20:22)
·小白入门:MySQL超详 (2025-12-26 23:20:19)