码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2021-06-20 18:21:18      阅读:0      评论:0      收藏:0      [点我收藏+]

标签: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<typename T>
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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!