Effective C++ 笔记(2):尽量以const,enum,inline替换#define

条款二(clause 2)

尽量使用const,enum,inline替换#define(以编译器替换预处理器)

1、使用const替换#define

通常替换

#define NUM 3.14

const double Num = 3.14;//大写名称用于宏,这里改变写法

其中有两种特殊情况:
1、定义常量指针(往往放在头文件中)两种写法:

const char* const authorName = "Scott Meyers";
const std::string authorName("Scott Meyers");

保证指针指向和指针指向的变量不会变。
2、class专属常量:为了让常量的作用域限制于class,通常采取这样的方式:

class GamePlayer{
private:
    static const int Numbers = 5;
    int scores[Numbers];
};

上述代码在C++中编译通过,但是我们通常说Class定义在头文件中,因此class中的成员“定义”通常称之为声明,这与标准定义是不相同的,如果想取某个class专属常量的地址,或者编译器不通过(非要你定义这个成员才行),这样你需要在实现文件中定义:

const int Gameplayer::Numbers;

但在我的编译器中加上这句会导致编译错误,因为编译器要求const常量在定义时必须规定好数值。
当然,无法利用#define创建class专属常量,因为#define不重视作用域。
如果你的编译器比较旧不支持上述的语法则这样写:

class CostEstimate{
private:
    static const double Factor;
};

const double CostEstimate::Factor = 1.35;

2、或者用enum hack

class GamePlayer{
private:
//    static const int Numbers = 5;
    enum {Numbers = 5};
    int scores[Numbers];
};

也可以编译通过。
取const得地址是合法的,取enum和#define的地址通常不合法,如果不想别人通过指针或者引用获取你的某个整数的地址,那么enum可以实现你的想法。另外enum和#define一样不会导致非必要的内存分配。

3、不用宏实现函数

别用这种函数

#define CALL_WITH_MAX(a, b) F((a) > (b) ? (a): (b))

使用

template <typename T>
inline void callWithMax(const T& a,const T& b)
{
    f(a > b ? a : b); //f为简单比较函数
}

这种写法有很多好处,它遵守作用域和访问规则。

虽然我们对预处理器的要求变低了,但#define和#include依然是必需品。

上一篇:【5】JAVA---地址App小软件(DeletePanel.class)(表现层)


下一篇:深度:带领国产数据库走向世界,POLARDB底层逻辑是什么? | 开发者必读(090期)