Effective C++ 条款2:尽量以const,enum,inline替换#define

2021-09-09 10:13

阅读:778

标签:private   string   整数   ber   允许   cal   class   public   声明   #define用来定义常量。 首先我们需要知道,#define会在预编译的时候,以字符串替换的形式被替换掉。假设我们#define AspectRatio= 1.635。如果AspectRatio在使用的过程中报错,编译器会直接提示1.635。如果这个宏是其他文件定义的,那么对于使用者而言,他甚至都不知道1.635是个什么东西。 下面还有两种特殊情况 定义常量指针 常量指针通常需要用两个const。即既限定指针指向对象无法改变,也限定无法通过指针改变对象值。因为如果用#define定义指针的话,通常定义的是一个常量地址。这个地址代表的一定是一个固定的东西,因此必须是指针常量。并且,我们当然也不希望通过地址值直接修改任何东西。所以也必须是常量指针。 下面是个例子。 const char* const author_name = "Scott Meyers"; 这里面定义的一个指针,就是指针常量。但通常我们用string而非char* const std::string author_name("Scott Meyers"); class专属常量 类中的常量,我们希望他只有一版,因此需要定义为静态的。 class GamePlayer{ private: static const int number_turns = 5; int scores[number_turns]; } 但由于上面的这个常量是写在类中的,因此只是一个声明,而非定义。在取地址的时候,如果这个常量是内置的整数型,int,char,bool,就没什么问题。但是如果是别的类,或者有的其他编译器不允许这样,那就要在外面定义一下。 const int GamePlayer::number_turns = 5; 因为C++要求任何东西都要被定义才能使用。 enum hack 上述问题还有一个解决方法,就是enum hack。枚举型的变量可以当成一个int使用。而且枚举型可能比const更像#define。因为const变量可以取地址,但是enum和#define都无法取地址。 class GamePlayer { private: enum {num_turns = 5}; int scores[num_turn]; } 滥用宏 这一块我们讨论一个小问题,就是把宏定义成非常复杂的函数。这样可能导致一些意外的结果。下面是个例子 #define CALL_WITH_MAX(a, b) f((a) > (b) ? (a) : (b)) int a = 5, b = 0; CALL_WITH_MAX(++a, b) 由于宏会直接替换,所以最后就成了 f((++a) > (b) ? (++a) : (b)) 很显然,我们只希望a自加一次,但是这里却加了两次。 解决这个问题的方法是使用模板内联函数 template inline void callWithMax(const T& a, const T& b) { f(a > b ? a : b) } #define 设计的通常都是些简单的函数,因此完全可以将他们设计成内联函数。最大的好处是,模板内联函数是个函数,他可以放在class当中。这样就可以为它设计访问性,比如public和private。但是宏定义是没有类中权限的。 结论 对于单纯常量,用const替换 对于形似函数的宏,最好用inline替换 Effective C++ 条款2:尽量以const,enum,inline替换#define标签:private   string   整数   ber   允许   cal   class   public   声明   原文地址:https://www.cnblogs.com/destinyzk/p/14906651.html


评论


亲,登录后才可以留言!