1

我需要定义一个生成唯一标识符的 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)。编译器拒绝静态变量的内联初始化。修复很简单,在实现文件中离线初始化它。因此,我的课程不能仅是标题,但我可以忍受。

  • 第 (1) 行定义了我的特殊常量实例。不幸的是,编译器失败了,说“预期的参数声明符”。

我也尝试过:static const Handle kUndefHandle = 0;但是编译器会抱怨“变量的类型‘句柄’不完整”,即使我把它放在子类中。而且我不能像在 Ruby 中那样在 C++ 中重新打开一个类。

我可以通过将该 const 实例声明放在类之外来使其工作。我失去了课程范围,但这是一个小缺点。如果我关心的话,我仍然可以使用命名空间。

但是,这仅在我将第 (2) 行中的构造函数公开时才有效。我不希望那样。我不想让程序员用任意值构造句柄。

有什么建议吗?

4

3 回答 3

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. (见ideone的例子

class FakeHandle : public Handle
{
public:
  FakeHandle(int val) : Handle(val) { }
};

现在可以这样做:

Handle badHandle = FakeHandle(5);
于 2012-06-07T15:58:01.937 回答
0

static const只有当成员是整数类型时,才能在类中初始化成员。这是一种特殊情况,一般规则是您必须将初始化放在 .cpp 文件中(连同您的静态非常量)。

于 2012-06-07T15:57:56.167 回答
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;
于 2012-06-07T15:58:24.177 回答