[C++] class专属常量
为了将常量的作用域限制于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
一样绝不会导致非必要的内存分配。