让自己习惯C++

条款2:尽量以const、enum、inline替换 #define

或者可以这样说,尽量用编译器处理预处理器。

#define ASPECT_RATIO 1.653

记号名称ASPECT_RATIO也许从未被编译器看见,也许在编译器开始处理源码之前它就被预处理器移走了,因此记号名称ASPECT_RATIO有可能没有进入记号表,当用此常量得到一个编译错误时,会感到困惑。

解决方法是以一个常量替换上述的宏(#define)

const double AspectRation=1.65;

作为一个语言常量,AspectRation肯定会被编译器看到,一定会进入记号表内。

这时有两种特殊情况:

1、定义常量指针时

由于常量定义式通常被放在头文件内,因此有必要将常量指针(不只是其指向的对象)声明为const,如:const std::string authorName("Scott Meyers")

2、class 专属常量

为了将常量的作用域限制于class内,必须让它成为class的一个成员,而为确保此常量至多只有一份实体,必须让它成为一个static成员

class GamePlayer
{
  private:
   static const int NumTurns=5;//常量声明式
   int scores[NumTurns]; 
   .........
};

只要不取专属常量的地址,声明之后便可以使用他们而无需提供定义式。

但如果需要取class专属常量的地址,则必须另外在实现文件中而非头文件中提供定义式如下:

const int GamePlayer::NumTurns;//NumTurn的定义
                               //由于声明时已经赋初值,所以定义时不可以再设初值

注意:我们无法用#define创建一个class专属常量,因为一旦宏被定义,它就在其后的编译过程中有效,并不重视作用域。
但是有的编译器不支持声明赋初值,那么你可以将赋初值放在定义式内

如果你的编译器不允许class内的static整数型常量完成初值设定,可改用枚举常量enum

理论基础是:一个属于枚举类型的数值可以充当整型使用。如下:
 

class GamePlayer
{
  private:
      enum{NumTurns=5};//令NumTurns成为5的一个记号名称
      int scores[NumTurns];
      .....
};

另一个常用的#define的误用情况,是用它实现形似函数的宏,这时你必须为每个实参添加小括号,但即使这样,有时也会出现错误

//以a和b的较大值调用f
#define CALL_WITH_MAX(a,b) f((a)>(b)?(a)>(b))

为了避免这种错误,我们可以用inline代替#define

template<typename T>
inline void callWithMax(const T&a,const T&b)
{
  f(a>b?a:b);
}

总结:对于单纯常量,最好以const对象 或enums替换#defines

            对于形似函数的宏,最好改用inline函数替换#defines

条款3    尽可能使用const 

const修饰指针,如果关键字const 出现在星号左边,则表示被指物是常量,如果出现在星号右边,表示指针自身是常量

const修饰迭代器:

std::vector<int>vec;
.....
const std::vector<int>::iterator iter=vec.begin();//iter的作用像个T*const
*iter=10;//没问题,改变iter所指的值
++iter;//错误!因为iter是const

std::vector<int>::const_iterator citer=vec.begin();//citer的作用像个const T*
*citer=10;//错误!citer指向的值是const
++citer;//没问题

const 用于函数声明:令函数返回一个常量值

const用于成员函数:
 

猜你喜欢

转载自blog.csdn.net/weixin_41413441/article/details/81089824
今日推荐