C++

[C++] class专属常量

2017-05-03  本文已影响143人  何幻

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

class GamePlayer{
private:

    // 常量声明式
    static const int NumTurns = 5;

    // 使用该常量
    int scores[NumTurns];
};

然而,NumTurns是常量的声明式而非定义式,通常C++要求你对你所使用的任何东西提供一个定义式。
但如果它是一个class专属常量又是static,且为整数类型(integral type,例如int,char,bool),则需特殊处理。
只要不取它们的地址,你可以声明并使用它们而无须提供定义式。

但如果你取某个class专属常量的地址,或纵使你不取其地址但是编译器却(不正确的)坚持要看到一个定义式,
你就必须另外提供定义式如下:

// NumTurns的定义
const int GamePlayer::NumbTurns;

请把这个式子放进一个实现文件,而不是头文件中。
由于class常量已在声明时获得初值,因此定义时不可以再设初值。

旧式编译器也许不支持上述语法,它们不允许static成员在其声明式上获得初值。
此外,所谓的“in-class初值设定”也只允许对整数常量进行。
如果你的编译器不支持上述语法,你可以将初值放在定义式:

class CostEstimate{
private:
    // static class常量声明,位于头文件
    static const double FudgeFactor;

    ...
};

// static class常量定义,位于实现文件中
const double CostEstimate::FudgeFactor = 1.35;

这几乎是你在任何时候唯一需要做的事,唯一例外的是在class编译期间需要一个class常量值,
例如,在上述的GamePlayer::scores的数组声明式中,
是的,编译器坚持必须在编译期间知道数组的大小。

这时候,万一你的编译器(错误的)不允许“static整数型class常量”完成“in-class初值设定”,
可改用所谓的“the enum hack”补偿做法。
其理论基础是:“一个属于枚举类型的数值可权充int被使用”。

于是GamePlayer可定义如下:

class GamePlayer{
private:
    // “the enum hack”,令NumTurns成为5的一个记号名称
    enum { NumTurns = 5 };

    // 这就没问题了
    int scores[NumTurns];

    ...
};

“enum hack”的行为某方面说比较像#define,而不像const
例如,取一个const的地址是合法的,但取一个enum的地址就不合法,而取一个#define的地址通常也不合法。
如果你不想让别人获得一个pointer或reference指向你的某个整数常量,enum可以帮助你实现这个约束。
此外,虽然优秀的编译器不会为“整数型const对象”设定另外的存储空间
(除非你创建一个pointer或reference指向该对象),不够优秀的编译器却可能如此,而这可能是你不想要的。
enum#define一样绝不会导致非必要的内存分配。


Effective C++ - P14

上一篇下一篇

猜你喜欢

热点阅读