1、你所使用的名称可能并未进入记号表
如 #define ASPECT_RATIO 1.653
中的记号名称ASPECT_RATIO可能由于预处理器的处理,而未被真实编译器看见,于是记号名称未能进入记号表。
解决方法:用编译器替换预处理器
即用const替换宏(#define)
const double AspectRatio = 1.653
作为一个语言常量,AspectRatio一定会被编译器看到,当然会进入记号表内。
2、#defines不能用来定义class专属常量
因为#defines并不重视作用域,除非被#undef;
也不提供封装性,不存在private #define这种东西。
解决方法:使用static const
如果将常量的作用域(scope)限制于class内,必须让它成为class的一个成员(member)。如果要确保此常量至多有一份实体,必须让它成为static成员。
class GamePlayer {
private:
static const int NumTurns = 5; // 常量声明式
int scores[NumTurns]; // 使用该常量
}
通常C++要求所使用的任何变量均需提供定义式,但如果它是一个class专属常量又是static且为整数类型(integral types, ints, chars, bools),则需特殊处理,只要不取它们的地址,可以只声明并使用它们而无需提供定义式;但如果你取某个class专属常量的地址,你就必须提供下面的定义式:
const int GamePlayer::NumTurns; // 定义
下面是static,const,static const 作为类成员的定义式的总结。
转自网友http://blog.csdn.net/livelylittlefish/article/details/5729894
类型 | 类中(声明) | 类外(类实现文件) | 构造函数体中 | 构造函数初始化列表 |
---|---|---|---|---|
非静态非常量数据成员 | N | N | Y | Y |
非静态常量数据成员 | N | N | N | Y(must) |
静态非常量数据成员 | N | Y(must) | N | N |
静态常量数据成员 | Y | Y | N | N |
the enum hack
旧式编译器可能不支持在类中设定初值的语法(这是c++11的语法),可以将初值放在定义式。如果此时常量作为数组的大小,可以采用the enum hack补偿做法。其理论基础是:一个属于枚举类型(enumerated type)的数值可以权充ints被使用
class GamePlayer{
enum {NumTurns = 5};
int scores[NumTurns];
};
the enum hack的特点:
- 无法取enum的地址,当你不想让别人获得一个pointer或reference指向你的某个整数常量时,enum可以实现
- enum和#define不会导致非必要的内存分配
3、形似函数的宏的缺点
#define CALL_WITH_MAX(a, b) f((a) > (b) ? (a) : (b))
- 必须为各个实参加括号
对于自增运算符的bug
int a = 5, b = 0; CALL_WITH_MAX(++a, b); //a累加一次 CALL_WITH_MAX(++a, b + 10); //a累加两次
解决方法:template inline函数
template<typename T>
inline void callWithMax(const T& a, const T& b)
{
f(a > b ? a : b);
}