4.设计与声明

Designs and Declarations #

18.Make interfaces easy to use correctly and hard to use incorrectly #

  • 好的接口容易被正确使用 ,不容易被误用

  • 阻止误用的办法包括建立新类型、限制类型上的操作,束缚对象值,以及消除客户的资源管理责任

19.Treat class design as type design #

  • Class的设计就是type的设计

  • 标准string和STL窗口都不被设计作为base classed使用,因为它们的析构函数都不带virtual

20.Prefer pass-by-reference-to-const to pass-by-value #

  • 对于内置类型,以及STL的迭代器和函数对象,使用pass-by-value更合适

  • C++编译器底层中的references往往是以指针方式实现的,意味着真正传递的是指针

21.Don’t try to return a reference when you must return an object #

当必须返回新对象时,就让那个函数返回新对象,如下

inline const Rational operator* (const Ratinal& lhs,const Rational& rhs)
{
    return Rational(lhs.n * rhs.n,lhs.d * rhs.h);//编译器会优化掉构造和析构的开销
}

不要返回pointer 或reference指向一个local stack 对象,也不要返回reference指向一个heap-allocated对象,也不要返回pointer或reference指向一个local static 对象,因为有可能 同时需要多个这样的对象

//不推荐
inline const Rational operator* (const Ratinal& lhs,const Rational& rhs)
{
    static Rational result;
    result = ...;
    return result;
}

22.Declare data members private #

切记将成员变量声明为private,利用封装性

23.Prefer non-member non-friend functions to member functions #

宁可拿non-member non-friend函数替换member函数

class WebBrowser{
public:
	void clearCache();
    void clearHistory();
    void remove Cookies();
};

class WebBrowser{
public:
	void clearEverything()
    {
 		clearCache();
    	clearHistory();
    	remove Cookies();              
    }
private:
	void clearCache();
    void clearHistory();
    void remove Cookies();    
};

//更推荐的做法
void clearBrovser(WebBrowser& wb)
{
 	wb.clearCache();
    wb.clearHistory();
    wb.remove Cookies();       
}

24.Declare non-membe functions when type conversions should apply to all parameters #

如果需要为某个函数的所有参数(包括被this指针所指的那个隐喻参数)进行类型转换,那么这个函数必须是个non-member

class Rational{
public:
    Rational(int numerator = 0,int denominator = 1);//允许隐式类型转换
    int numerator() const;
    int denominator() const;
public:    
	const Rational operation*(const Rational& rhs) const;
};

Rational oneEighth(1,8);
Rational oneHalf(1,2);
Rational result = oneHalf * oneEighth;
result = result * oneEighth;
result = oneHalf * 2;//OK  隐式类型转换
result = 2 * oneHalf;//==>2.operator*(oneHalf)  错误
class Rational{
	...
};

const Rational operator*(const Rational& lhs,const Rational& rhs)
{
    return Rational(lhs.numerator() * rhs.numerator(),
                    lhs.denominator() * rhs.denominator());
}
Rational oneFourth(1,4);
Rational result;
result = oneFourth * 2;//OK  隐式类型转换
result = 2 * oneFourth;//OK  隐式类型转换

25.Consider support for a non-throwing swap #

std::swap对你的类型效率不高时,提供一个swap成员函数,并确定这个函数不抛出异常


namespace WidgetStuff{
    template<typename T>
    class Widget{
        ...
    	void swap(Widget& other)
        {
            using std::swap;
            swap(pImpl,other.pImpl);
        }
    };
    ...
    template<typename T>
    void swap(Widget<T>& a,Widget<T>& b)
    {
        a.swap(b);
    }
}
template<typename T>
void doSomething(T& obj1,T& obj2)
{
    using std::swap();
    swap(obj1,obj2);//为T类型对象调用最佳swap版本
}