const,enum,inline
替换 #define
宏:#define
命令是C语言中的一个宏定义命令,它用来将一个标识符定义为一个字符串,该标识符被称为宏名,被定义的字符串称为替换文本。
示例代码中#define plus(x) x+x
表示用X+X这个字符串代替plus(x)
#include
using namespace std;
#define plus(x) x+x
int main(){
int res = plus(2*2);
cout<<res<<endl;
system("pause");
return 0;
}
#include
using namespace std;
#define square(x) x*x
int main(){
int res = square(2+2);
cout<<res<<endl;
system("pause");
return 0;
}
上述例子中宏定义了square(x)替换为x*x,表面上看是一个类似求平方的函数,但编译器实际处理的指令为:2+2×2+2 = 8,以此可见宏定义的“替换”性质。
正确的求平方宏定义:
#include
using namespace std;
#define plus(x) x+x
#define square(x) (x)*(x)
int main(){
int res = square(2+2);
cout<<res<<endl;
system("pause");
return 0;
}
#define 不被视为语言的一部分
例:#define ASPECT_RATIO 1.653
const double AspectRatio 1.653;
const
替换#define
的特殊情况:const char* const authorName = "Scott Meyers";
代码中第一个const说明指向对象的内容不可改变,第二个const说明该指针指向的对象是固定的。
更好的做法(至于为什么见条款03):使用string指针:
const std::string authorName = "Scott Meyers";
class GamePlayer {
private:
static const int NumTurns = 5; //常量声明式
int scores[NumTurns]; //使用该常量
...
};
...
const int GamePlayer::NumTurns; //NumTurns的定义式,位于源码中
上述示例中,类的内部对常量NumTurns进行了声明,但在源码中才为其创建了实例,注意到源码定义式中没有设置初值,因为在类中已经设置过了。
如果编译器不允许in-class设置初值,同样可以这样写:
class GamePlayer {
private:
static const int NumTurns; //常量声明式(未设置初值)
//int scores[NumTurns]; //使用该常量
...
};
...
const int GamePlayer::NumTurns = 5; //NumTurns的定义式,位于源码中
注意:#define不仅不能够用来定义class的专属常量,也不能够提供任何的封装性(宏是面向全局的)
注意到在上述class专属常量的定义中,如果编译器不允许in-class设初值时,则无法在class内使用该常量(NumTurns),而#define又无法进入class的内部,此时可以使用枚举类型enum来处理:
enum student{xiaoming, lihong, zhaohua};
其中stuent是类型名称,三个名字是类型的所有合法值。class GamePlayer {
private:
enum { NumTurns = 5}; //enum hack:令NumTurns成为5的一个记号名称
int scores[NumTurns]; //现在可以使用该常量
...
};
#define CALL_WITH_MAX(a,b) f((a) > (b) ? (a) : (b))
上述#define将CALL_WITH_MAX(a,b)
替换为函数f((a) > (b))? (a) : (b))
注意到我们已经改正了2.中的错误将每一个参数都加上了小括号,但是仍然会出现以下诡异的事情:
int a = 5, b = 0;
CALL_WITH_MAX(++a, b); //a被累加两次
CALL_WITH_MAX(++a, b+10); //a被累加一次
因为编译器实际执行的为:
++a ,a > b → ++a;
++a ,a < b → b;
template<typename T>
inline void callWithMax(const T& a, const T& b){
f(a > b ? a : b);
}
使用template产出一整群函数,每个函数接受两个同型对象,并以其中较大者调用函数f
使用const、enum、inline
可以减少对预处理器的需求,但是仍然无法完全消除(#include是必要的),在非必要场景下,请多多使用const、enum、inline