「C++」条款02 & 03:#define & const

  •  关于 #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;

 

posted @ 2013-06-08 10:45  kedebug  阅读(600)  评论(0编辑  收藏  举报