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)はコンパイルされません(Clang3.x)。コンパイラーは、静的変数のインライン初期化を拒否します。修正は簡単です。実装ファイルでオフラインで初期化します。したがって、私のクラスをヘッダーのみにすることはできませんが、それを使用することはできます。

  • 行(1)は、私の特別な定数インスタンスを定義します。残念ながら、コンパイラは「期待されるパラメータ宣言子」と言って失敗します。

私も試しました:しかし、サブクラスに入れてもstatic const Handle kUndefHandle = 0;、コンパイラは「変数の型が不完全です'Handle'」と文句を言います。そして、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) { }
};

今、1つができる:

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

static constメンバーは、それらが整数型である場合にのみ、クラス内で初期化できます。これは特殊なケースであり、一般的なルールとして、初期化を.cppファイルに(静的なnon-constとともに)配置する必要があります。

于 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 に答える