C++程序中尽量避免#define

使用const,enum替换#define定义常量

C语言中常用#define来定义具有某种特殊意义的常量。但是,使用#define宏定义定义的符号会在编译前被替换掉,当因为该宏定义出现问题时,在错误信息中无法获得有关该宏的任何提示,这对错误的发现带来困难,,尽管可以通过查看预编译输出的方式尝试定位问题。同时预处理也会在程序中产生多份副本,造成代码量较大。

为了解决这些问题,可以使用const常量替代宏定义的常量,这样定义的常量会被加入记号表内,而被编译器看到,同时所有使用该常量的地方都是对同一个常量的引用,不会出现多份的情况。

/****************************************
 * const_value.cpp                      *
 *                                      *
 * C++高效原则之一用const代替#define    *
 ****************************************/

#include <iostream>

int main()
{
  const int PRICE = 10.0;

  std::cout<<"输入数量: "<<std::endl;
  int x;
  std::cin>>x;

  std::cout<<"总价为: "<<PRICE * x<<std::endl;

  return 0;
}

const常量替代#define
在这个例子中,发现一个问题,就是C++cin输入回显是要换行的,而C语言中的scanf却不用。上例中,前一个是C程序,使用printf输出,scanf输入回显不换行,第二个是C++程序,使用cout输出,cin输入。

在使用const与指针结合时,有两种不同的形式,一种是指针常量,使用类似const char *的定义,说明该指针指向的内存地址里的内容不可改变,另一种是常量指针,使用类似char* const定义,说明指针本身是个常量,它不能指向当前所指地址外的其他地址。

指针常量可以改变指向的地址,但不可以通过指针改变地址内的值。

/****************************************
 * pointer_const.cpp                    *
 *                                      *
 * C++指向常量的指针(指针常量)            *
 ****************************************/

#include <iostream>

int main()
{
  int a = 10;
  int b = 20;
  const int *p = &a;
  p = &b;

  *p = 30;

  return 0;
}

指针常量
常量指针可以改变地址内的值,但不可以改变指针指向

/*****************************************
 * const_pointer.cpp                     *
 *                                       *
 * 常量指针                              *
 *****************************************/

#include <iostream>

int main()
{
  int a = 20;
  int* const p = &a;
  *p = 30;

  int b = 50;
  p = &b;

  return 0;
}

常量指针
const类型常量可以用以定义类常量,类常量是类中的一个static const成员,它的作用域为类内,且在各个对象中共享一份。当类常量是基本类型时,只要不取它们的地址,可以声明并使用它们而无需定义式。如果需要取它们的地址,或者编译器不支持以上原则,则需要在定义文件中额外提供类常量的定义式。如果在声明式子中已设置初值(有些编译器不支持,必须将初始化放于定义式中),则在定义式中就不能在设置初值。而在这一方面,宏定义无法来定义类常量,它缺乏作用域的限定,不具有封装性。

//-*-C++-*-

class GamePlayer
{
private:
  static const int NumTurns = 5;

public:
  void PrintNumTurns();
};
#include "GamePlayer.h"

#include <iostream>

void GamePlayer::PrintNumTurns()
{
  std::cout<<"NumTurns = "<<NumTurns<<std::endl;
}

int main()
{
  GamePlayer a;
  a.PrintNumTurns();
}

简单类型常量只声明
若只在类中提供类常量声明式,当试图引用指针时,就会报错:

//GamePlayer.cpp
#include "GamePlayer.h"

#include <iostream>

void GamePlayer::PrintNumTurns()
{
  std::cout<<"NumTurns = "<<NumTurns<<std::endl;

  const int *p = &NumTurns;

  std::cout<<"NumTurns = "<<*p<<std::endl;
}

int main()
{
  GamePlayer a;
  a.PrintNumTurns();
}

静态常量无定义式

在定义文件中添加定义式即可。

//GamePlayer.cpp
#include "GamePlayer.h"

#include <iostream>

const int GamePlayer::NumTurns;

void GamePlayer::PrintNumTurns()
{
  std::cout<<"NumTurns = "<<NumTurns<<std::endl;

  const int *p = &NumTurns;

  std::cout<<"NumTurns = "<<*p<<std::endl;
}

int main()
{
  GamePlayer a;
  a.PrintNumTurns();
}

静态常量定义式
当对定义的整型常量 需要某些类似宏的行为时,例如不能取地址,不会导致额外的存储空间,可以使用enum hackenum hack利用枚举类型的数值来充当整型使用。

//GamePlayer.h
//-*-C++-*-

class GamePlayer
{
private:
  enum {NumTurns = 5};

public:
  void PrintNumTurns();
};
//GamePlayer.cpp
#include "GamePlayer.h"

#include <iostream>

void GamePlayer::PrintNumTurns()
{
  std::cout<<"NumTurns = "<<NumTurns<<std::endl;
}

int main()
{
  GamePlayer a;
  a.PrintNumTurns();
}

枚举常量

使用inline函数替换形似函数的宏

C语言中常定义类似于函数的宏,尽管这样的宏有不带来函数调用的额外开销,但这样定义的宏很容易出现问题。在C++中,可以使用template inline函数获得宏带来的效率以及一般函数的所有预料行为和类型安全性。

//-*-C++-*-
//GamePlayer.h
#define MAX(a, b) a > b ? a : b

class GamePlayer
{
private:
  template<typename T>
  inline T max(const T& a, const T& b);
public:
  void PrintMaxUsingMacro();
  void PrintMaxUsingInlineFunction();
};
//GamePlayer.cpp

#include "GamePlayer.h"

#include <iostream>

template<typename T>
T GamePlayer::max(const T& a, const T& b)
{
  return a > b ? a : b;
}

void GamePlayer::PrintMaxUsingMacro()
{
  int a = 20;
  int b = 30;
  std::cout<<"a和b中最大的值是"<<(MAX(a,b))<<std::endl;
}

void GamePlayer::PrintMaxUsingInlineFunction()
{
  int a = 20;
  int b = 30;
  std::cout<<"a和b中最大的值是"<<max(a,b)<<std::endl;
}

int main()
{
  GamePlayer a;
  a.PrintMaxUsingMacro();
  a.PrintMaxUsingInlineFunction();
}

inline函数

参考文献

  1. Scott Meyers著,侯捷译. Effective C++中文版. 电子工业出版社. 2012.
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值