Effective C++ 第四章

4. Designs and Declarations 设计与声明

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

让接口容易被正确使用,不易被误用

促进正确使用:

  • 保持接口的一致性,如STL容器都有一个名为size的成员函数
  • 与内置类型的行为兼容

防止错误使用:

  • 建立新类型、限制类型上的操作,如不直接返回指针,而是返回智能指针,避免客户忘记delete

  • 束缚对象值

    导入 外覆类型(wrapper types)区分年、月、日

    Date d(Month::Mar(), Day(30), Year(1995));

19:Treat class design as type design.

设计class犹如设计type

设计class需要考虑的问题:

  • 新type的对象如何被创建和销毁(第八章)

    构造函数、析构函数、内存分配函数和释放函数

  • 对象的初始化和赋值有什么差别(条款4)

    构造函数和赋值操作符

  • 以值传递如何实现

  • 新type的合法值

  • 是否需要继承(条款34、36)

  • 类型转换(条款15)

  • 合法的操作符(条款23、24、46)

  • 成员变量、成员函数的访问控制

  • 未声明接口(条款29)

  • class or class template

  • 是否需要新的type,或者增加非成员函数即可

 

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

  • 传递对象给函数参数,pass-by-value会增加调用构造函数和析构函数的成本,引用传递可以避免

  • const类型,避免对原始对象的修改

  • 可以避免切割(slicing)问题:

    派生类对象传递给函数参数的基类对象,派生类的特化性质会被切割掉,只剩下基类对象

    引用传递可以实现多态,解决切割问题

  • 例外:

    内置类型、STL的迭代器、函数对象

 

21: Don't try to return a reference when you must return an object.

必须返回对象时,别妄想返回其reference

  • 不要返回指向局部的、堆上的或static的对象的指针/引用
  • 直接返回对象,交给编译器优化

有理数乘法的正确实现版本

inline const Rational operator*(const Rational& a, const Rational& b) {
	return Rational(a.n*b.n, a.d*b.d);
}

 

22: Declare data members private.

将成员变量声明为private

pirvate的成员变量,可以

  • 划分访问控制
  • 实现封装,给客户提供一致性的函数接口
  • 声明为protected的变量,修改或取消同样会引发所有继承类的改变
  • 封装的角度,只有两种访问权限:private和其他

 

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

 

24: Declare non-member functions when type conversions should apply to all parameters.

若所有的参数都需要类型转换,请为此采用non-member函数

要使下面的代码通过编译:

class Rational {
public:
    Rational(int numerator=0, int denominator=1); // 构造函数不为explicit,允许int隐式转换为Rational
    int numerator() const;
    int denominator() const;
private:
    ...
};

Rational a(1, 4);
Rational result;
result = a * 2;
result = 2 * a;

有理数乘法应该设计为non-member:

const Rational operator*(const Rational& a, const Rational& b) {
    return (a.numerator()*b.numerator(), a.denominator()*b.denominator());
}

可以避免fiend函数就该避免,这里不需要设计成为friend函数

 

25: Consider support for a non-throwing swap.

考虑写出一个不抛异常的swap函数

posted @ 2020-09-21 20:53  izcat  阅读(157)  评论(0编辑  收藏  举报