《Effective C++》

1. 让自己习惯C++

01. 视 C++ 为一个语言联邦

四个次语言

  • C
  • Object-Oriented C++
  • Template C++
  • STL

请记住

  • C++ 高校编程守则视情况而变化

02. 尽量以 const,enum,inline,替换 #define

可以理解为“宁可以编译器替换预处理器”,因为 #define 不被视为语言的一部分

有两种特殊情况值得注意:

  1. 定义常量指针(const pointers)

    若要在头文件内定义一个常量的 char*-based 字符串,必须写 const 两次:

    1
    const char* const author_name = "Wablers Liu";

    不过,string 对象通常比 char*-based 合宜,所以定义成这样往往更好:

    1
    const std::string author_name = "Wablers Liu";
  2. class 专属常量

    为将常量的作用域(scope)限制于 class 内,必须让它成为 class 的一个成员(member);而为确保此常量至多就一份实体,必须让它成为一个 static 成员:

    1
    2
    3
    4
    5
    6
    class GamePlayer {
    private:
    static const int kNumTurns = 5; // 常量声明式
    int scores[kNumTurns]; // 使用该常量
    ...
    };

    新型编译器中可以这样定义:

    1
    const int GamePlay::kNumTurns; // kNumTurns的定义

    这个式子要放进一个实现文件而非头文件。因为 class 常量已在声明时获得初值,所以此处定义时不可以再设初值。

    倘若旧式编译器不支持上述语法,则可以将初值放在定义式:

    1
    2
    3
    4
    5
    6
    7
    class CostEstimate {
    private:
    static const double kFudgeFactor; // static class常量声明
    ... // 位于头文件
    };

    const double CostEstimate::KFudgeFactor = 1.35; // static class常量定义, 位于实现文件

    万一你的编译器(错误地执行)不允许“static 整数型 class 常量”完成 “in class 初值设定”,则可以改用”the enum hack“:

    1
    2
    3
    4
    5
    6
    7
    8
    class GamePlayer {
    private:
    enum { // 枚举
    kNumTurns = 5;
    };
    int scores[kNumTurns]; // 使用该常量
    ...
    };

    同时,且勿用 #define 来实现一个像函数的宏,此举不会调用函数但会带来额外的开销。如下面的宏:

    1
    #define CALL_WITH_MAX (a, b) f((a) > (b) ? (a) : (b))

    这种宏有着太多的缺点,一旦忘记在所有实参上加小括号,则会导致各式麻烦。

    所以直接采用 template inline 形式:

    1
    2
    3
    4
    template<typename T>
    inline void CallWithMax(const T& a, const T& b) {
    f(a > b ? a : b);
    }

    请记住

  • 对于单纯常量,最好以 const 对象或者 enums 替换 #define
  • 对于形似函数的宏(macros),最好改用 inline 函数替换 #define