1.用const替换#define(宁可编译器替换预处理器)
理由:假设#define sign 1.653,当你使用这个宏定义的时候,在预处理期间在你使用sign的地方就被替换为1.653,sign有可能没有进入记号表中,这个时候当此处发生错误,错误可能提示的是发生在1.653,当程序很大时或者sign被定义在其他文件时,你会对于1.653很迷惑不知道来自何处,于是将追踪它而浪费时间,所以用const替换#define,如写成const double sign=1.653.
注意:在使用const替换#define的时候,要注意两个特殊的情况:
1.定义常量指针:const int *const p;
在定义常量字符串的时候:const char * const p="hello,world",将指针变量自身和指针指向的内容都用const修饰,但往往定义字符串常量的时候string通常比char *好用,所以定义成:const std::string author="hello,world"更好
2.定义class的专属常量:
为了确保const成员只有一个实体,通常使用static将其声明为静态常量,但是在类中的声明仅仅是声明,类中不存在定义,即使形如
class Const
{
public:
static const int n = 5;//仅仅是声明
int arr[n];//可以使用该常量
};
const int Const::n;//此处是定义,因为在声明的时候已经赋值,所以在此处不可赋值
C++要求你对所有使用的任何东西都需要提供定义式,但是如果他是class一个专属常量又是static且为整数类型(ints,chars,bools),需特殊处理,只要不取class专属常量的地址声,可以声明并使用他们无须定义,但是C++老版本不支持在类中对static成员在其声明式上获得初始值,所以你只能将初始值放在定义式,代码如下:
class Const
{
public:
//static const int n = 5;//错误c++老版本不支持
static const int n;//应该这样写
};
const int Const::n=5;//定义处赋值
(宏定义不能创建一个class的专属常量,因为其无视作用域,所以他也不能提供任何封装性,当然const成员是可以被封装的。)
在上述老版本不支持的代码中,加入有一个数组在编译期间要使用这个常量值,而老版本又不支持在声明时赋值,该怎么办呢?这就需要用到enum了
class Const
{
public:
static const int n;
int arr[n];//编译无法通过
};
2.enum
当上述代码无法实现的时候,我们可以用enum轻松解决,代码如下:
class Const
{
public:
enum{ n = 5 };//使用枚举
int arr[n];
};
下面来说说enum:enum有些方面更像是#define而不是const,比如:取一个const的地址是合法的,但是取一个enum的地址就不合法,而取一个enum的地址也不合法。如果你不想让别的指针或者引用指向你的整数常量,enum可以完成这个工作。虽然优秀的编译器不会为整数型const对象设定另外的储存空间,除非你想创建一个指针或者引用指向该常量,但是不够优秀的编译器或许会给其另外设置储存空间,所以使用enum绝对不会导致这种事情的发生
3.inline
有时候用#define实现所谓的宏函数,虽然不会导致函数调用带来额外的开销,但是有着太多的缺点比如下面的代码:
#define Max(a,b) f((a)>(b)?(a):(b))
加一堆括号看着都让人头大,还会有一堆的其他问题,这个时候inline就派上用场了,只要你写出一个模板inline函数就解决了宏带来的麻烦
template<class T>
inline void max(const T& a, const T& b)
{
return a > b ? a : b;
}