我需要定义一个生成唯一标识符的C ++类。我们的想法是每个可见类的每个实例都将由唯一的整数值标记。我们称之为实例的“句柄”。句柄在系统中的所有实例中必须是唯一的。
某些实例可能与其他实例相关,在这种情况下,它们的类定义了一个成员来存储其亲属的句柄。
但并非所有实例都有亲戚。所以我需要一个特殊的句柄值来代表一个“未定义的”亲戚。
我需要帮助来定义该特殊实例。这是我试过的:
class Handle {
public:
Handle(): mValue(newValue()) {};
static const Handle kUndefHandle(0); // (1)
protected:
Handle(int val): mValue(val) {}; // (2)
int mValue;
static int mNextValue = 1000; // start at 1000. (3)
static int newValue() { return mNextValue++; }
};
注意:
第(3)行不编译(Clang 3.x)。编译器拒绝静态变量的内联初始化。修复很简单,在实现文件中将其初始化。所以我的班级不能只是标题,但我可以忍受。
line(1)定义了我的特殊常量实例。不幸的是,编译器失败了,说“Expected parameter declarator”。
我也试过:static const Handle kUndefHandle = 0;
然后编译器抱怨“变量有不完整类型'Handle'”,即使我把它放在子类中也是如此。而且我不能像在Ruby中一样用C ++重新打开一个类。
我可以通过将const实例声明放在类之外来使其工作。我失去了班级范围,但这是一个小缺点。如果我关心,我仍然可以使用命名空间。
然而,这仅在我将第(2)行中的构造函数设为公开时才有效。我不希望这样。我不想让程序员构造具有任意值的句柄。
有什么建议吗?
答案 0 :(得分:2)
这对我有用:
class Handle {
public:
Handle(): mValue(newValue()) {};
static const Handle kUndefHandle;
protected:
Handle(int val): mValue(val) {};
int mValue;
static int mNextValue;
static int newValue() { return mNextValue++; }
};
const Handle Handle::kUndefHandle(0);
int Handle::mNextValue = 1000;
初始化静态类成员实际上被认为是在类的范围内,因此您可以在该上下文中访问私有和受保护的构造函数。
请注意,您应该将构造函数设为私有,因为当前存在一个漏洞,人们可以通过这个漏洞构造具有任意值的句柄:派生类,链到受保护的构造函数,然后转换结果对象到Handle
。 (See an example on ideone)
class FakeHandle : public Handle
{
public:
FakeHandle(int val) : Handle(val) { }
};
现在可以做到:
Handle badHandle = FakeHandle(5);
答案 1 :(得分:0)
static const
成员只有在它们是整数类型时才能在类中初始化。这是一种特殊情况,一般规则是你必须将初始化放在.cpp文件中(以及你的静态非const)。
答案 2 :(得分:0)
这是一个让你入门的骨架:
class Foo
{
static int const undef_handle;
static int next_handle;
static int get_handle() { return ++next_handle; }
int const my_handle;
int const related_handle;
public:
Foo()
: my_handle(get_handle())
, related_handle(undef_handle)
{ }
Foo(int h)
: my_handle(get_handle())
, related_handle(h)
{ }
// Copy/move constructors, assignment, ...
};
int Foo::next_handle = 1000;
int const Foo::undef_handle = 0;