tangjikede 2018-07-21
条款 01:视C++为一个语言联邦
View C++ as a federation of languages
如今的C++是个多重范型编程语言(multiparadigm programming language),它支持如下形式:
最简单的办法是把它看作一个由相关次语言组成的联邦:
条款 02:尽量以const,enum,inline替换#define
Prefer consts,enums,and inlines to #defines
宁肯以编译器替换预处理器!因为#define不被看作语言的一部分
当你做出如下定义:
#define ASPECT_RATIO 1.653
它在编译器开始处理源码之前就被预处理器移走,编译器不会看到它,所以它也不存在于记号表(symbol table)中。当你使用这个常量报错时会发现,错误信息也许会提到1.653而非ASPECT_RATIO,你将因为追踪它而浪费时间。
解决办法就是以常量替换宏定义:
const double AspectRatio = 1.653
它的另外一个优点是缩短代码长度,因为预处理器会盲目的将ASPECT_RATIO替换为1.653导致出现多份1.653。
两种特殊情况
声明和定义:声明和定义是完全同的概念,声明是告诉编译器“这个函数或者变量可以在哪找到,它的模样像什么”。而定义则是告诉编译器,“在这里建立变量或函数”,并且为它们分配内存空间。
一般C++要求你给你使用的任何东西提供一个定义式,除非它是class专属常量&&static类型&&整数类型(ints、chars、bools),只要不取地址就无须写定义式。
非要看定义式的话、给你
const int GamePlayer::NumTurns;
需要注意!这个式子要放在实现文件而非头文件,原因往上瞅瞅。
其实这就是“in-class”初值设定(在编译期间需要一个class常量值,只针对整数常量):声明时设定初值,定义时不再设。当然如果不是整数类型的话也可以定义时再设初值。
enum hack补偿法
如果恰巧编译器秀逗了,你还可以使用枚举法设定初值:
class GamePlayer{
private:
enum { NumTurns = 5 };
int scores[NumTurns];
......
};
enum还有以下优点:
inline
一个常见的#define误用情况是去实现宏(macros),宏看起来像函数,但它不会招致函数调用带来的额外开销。
来看一个简单的宏:
// 以a和b的较大值调用f
#define CALL_WITH_MAX(a,b) f( (a) > (b) ? (a) : (b) )
宏有两个特点
用inline函数代替
template<typename T>
inline void callWithMax( const T& a, const T& b){
f( a > b ? a : b );
}
此外由于它是一个真正的函数,它遵守scope(作用域)的概念和访问规则,因此,完全可以封装在类内,这是宏无法做到的。