Effective C++ 条款2

本文探讨了在C++编程中,如何通过使用const, enum和inline替代#define预处理器指令来提升代码质量和效率。文章详细解释了预处理器宏的局限性,以及使用现代C++特性如const对象和enum枚举的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

条款02:尽量以const,enum,inline替换 #define
1、条款改为宁愿用编译器也不用预处理器, 因为#define不被视为语言的一部分,所以就来了问题。

2、#define ASPECT_RATIO 1.653
这个宏ASPECT_RATIO不被编译器所见,是在被预处理器处理掉了,所以这个名称有可能没有进入记号表内。当运行此变量但是获得一个编译错误时,这个错误会提到1.653而不是这个变量,如果这个变量被定义在别人所写的头文件里,你可能会浪费时间。原因就是所使用的的名称未进入记号表中。
还是用常亮来替换上面的宏:

	const double AspectRatio = 1.653;

作为一个语言常亮,AspectRatio肯定会被编译器处理,就会进入记号表内,此外对浮点常量来说,使用常量可能比使用宏导致较小的码,因为预处理器将宏替换可能导致目标码出现多份。
当我们以常量来替换宏,有两种特殊情况值得说说。第一是定义常量指针。我们通常将常量定义式放在头文件中,因此有必要将指针(而不只是指针所指之物)声明为const。例如若在头文件内定义一个常量的(不变的)字符串,就要写成:const char* const authorName = “yy”;
const与指针的使用会在条款3中完整叙述,所以上述定义成const std::string authorName(“yy”);会好一些。

第二个值得注意的是class专属常量。为了将常量的作用域限制在class内,必须将它成为class的一个成员;而为确保此常量至多只有一分实体,必须让其成为一个static成员:

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

你所看到的是num的声明式而非定义式。通常C++要求所使用的的任何东西提供一个定义式,但是如果他是个class专属常量又是static且为整数类型,则需要特殊处理。只要不取她们的地址,,就可以声明并使用他们而无需提供定义式,但是你取某个class专属常量的地址,或纵使你不取其他地址而你的编译器却(不正确)坚持要看到定义式,你就必须另外提供定义式:const int GamePlayer::num;

请把这个式子放进一个实现文件而非头文件。由于class常量已在声明时获得初值(例如先前声明num时为5),因此定义时不可以再设初值。注意: 我们无法利用#define创建一个class专属常量,因为#define并不重视作用域,一旦宏被定义,它就在其后的编译器过程中有效。这意味着#define不仅不能用来定义class专属常量,也不能提供任何封装性。
旧式编译器也许不支持上述语法,他们不允许static成员在其声明上获得初值,此外所谓的"in-class初值设定"也只允许对整数常量进行。如果你的编译器不支持上述语法,你可以将初值放在定义式内。
这时候当你在class编译期间需要一个class常量值,像上述的GamePlayer::scores的数组声明中(是的,编译器坚持必须在编译期间知道数组的大小),这时候万一你的编译器不予许"static整数型class常量"完成在类中初值设定,可以改用所谓的“the enum hack”做法,定义如下:

class GamePlayer
{
private:
		enum{num = 5};
		int scores[num];
};

基于整个理由enum hack值得我们认识。如果你不想让别人获得指针或者引用指向你的整数常量,enum可以帮你实现这个约束。Enums和#defines不会导致非必要的内存分配。
虽然宏的缺点太多,有了const,enum,inline,我们对预处理器的需求降低了,但并非完全消除,#include仍然是必需品.

记住:对于单纯常量,最好以const对象或enum替换define。
对于形似函数的宏,最好改用inline函数替换define.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值