- 关于 #define
#define ASPECT_RATIO 1.63 const int AspectRatio 1.63;
如果我们的代码中用到了 ASPECT_RATIO 宏,编译器只会简单粗暴的把其替换为 1.63,如果后期我们调试的过程中莫名其妙的遇到了 1.63 可能追踪半天都不会清楚问题发生在什么地方。另外每次的替换,相当于扩大了代码体积,违背了重用的原则。再来看看 const 下定义的 AspectRatio,完全避免了上面几种情况的发生。
#define 往往也会在我们意料之外出错,如下面的情况:
#define MAX_NUM ((a) > (b) ? (a) : (b)) int a = 5, b = 0; MAX_NUM(++a, b); MAX_NUM(++a, b + 10);
第一个 MAX_NUM 宏 ++a 执行了 2 次,而第二个只执行了 1 次,这显然不是我们想要达到的效果,下次还是老老实实写成函数吧。
- static const
以前用类封装函数的时候,想着定义一个 const 常量,而且控制在类的作用域里面。下面的代码展示了几种可行的情况:
class GamePlayer { private: static const int NumTurns = 5; int scores[NumTurns]; ... }; class GamePlayer { enum { NumTurns = 5 }; int scores[NumTurns]; ... };
- const 的几种情况
关于 const 的几种定义就不在叙述了,下面主要针对 const 的几种关键用法:
class BigNum { }; const BigNum operator * (const BigNum& lhs, const BigNum& rhs);
这里不禁会有疑惑,为什么我们没有 return by reference 却加了一个 const 的在函数前面呢?想想如下情况:
BigNum a, b, c; if (a * b = c) { ... }
如果有人粗心的把 == 写成 = 就会引发程序的逻辑错误,如果设置返回为 const 的话,编译器就会帮助我们检测出来这些低级的逻辑问题。
再考虑关于“const 成员函数”的用法,也是 C++ const 几种经典案例之一:
class CTextBlock { public: const char& operator[] (size_t position) const { ... ... return text[position]; } char& operator[] (size_t position) { ... ... return text[position]; } private: char* text; }; // 此时调用 const 成员函数 void print(const CTextBlock& ctb) { cout << ctb[0]; } // 此时调用 non-const 成员函数 void print(CTextBlock& tb) { cout << tb[0]; }
也许你会发现两个成员函数执行的操作会是相同的,这样无疑重复了很多代码量,书中给出了下面的一种做法,让 non-const 调用 const 成员函数:
const char& operator[] (size_t position) const { ... ... return text[position]; } char& operator[] (size_t position) { ... ... ... return const_cast<char&> // 去掉 const 属性 (static_cast<const CTextBlock&> // 为 *this 加上 const (*this)[position]); // 调用 const op[] }
最后还有一个要点就是,对于编译器来说,const 成员函数里面是不允许修改类成员变量的,这有时候会给我们带来麻烦,但是可以通过关键字 mutable 来解决,例如:mutable size_t length;