0

列挙型の宣言や文字列の使用を避けようとしています。そうする理由は疑わしいように思われるかもしれませんが、完全な説明は無関係です。

私の質問はかなり単純です。メンバー変数のアドレスを一意のIDとして使用できますか?

より具体的には、要件は次のとおりです。

  • IDをシリアル化する必要はありません。
  • IDは保護されたメンバーになります-所有するオブジェクトによって内部的にのみ使用されます(同じクラスインスタンス間でもIDの比較はありません)。
  • サブクラスは基本クラスIDにアクセスする必要があり、新しいIDを追加できます。

したがって、最初の解決策は次のとおりです。

class SomeClass
{
    public:
        int mBlacks;

        void AddBlack( int aAge )
        {
            // Can &mBlacks be treated as a unique ID?
            // Will this always work?
            // Is void* the right type?
            void *iId = &mBlacks;

            // Do something with iId and aAge
            // Like push a struct of both to a vector.
        }
};

2番目の解決策はこれですが:

class SomeClass
{
    public:
        static int const *GetBlacksId()
        {
            static const int dummy = 0;
            return &dummy;
        }

        void AddBlack( int aAge )
        {
            // Do something with GetBlacksId and aAge
            // Like push a struct of both to a vector.
        }
};
4

1 に答える 1

2

このオブジェクトの他のintデータメンバー、および同じプロセス内のmBlacks別のインスタンスのメンバーは、のこのインスタンスのメンバーSomeClassと同じアドレスを持っていません。したがって、プロセス内で一意のIDとして安全に使用できます。mBlacksSomeClass

の空の基本クラスサブオブジェクトはSomeClassと同じアドレスを持つことができmBlacksSomeClass空の基本クラスがある場合はそうではありません)、charの最初のバイトであるオブジェクトmBlacksはと同じアドレスを持ちますmBlacks。それを除けば、同じアドレスを持つオブジェクトは他にありません。

void*タイプとして機能します。int*も機能しますが、IDごとに異なるタイプのデータメンバーを使用したい場合があります。

ただし、IDはこのインスタンスに固有です。同じタイプの別のインスタンスは別のIDを持っています。あなたのコメントの1つは、これが実際にはあなたが望んでいるものではないことを示唆しています。

タイプの各に一意のIDを設定し、同じ値を持つすべてのオブジェクトに同じIDを設定する場合は、オブジェクトのすべての重要なフィールドからIDを作成することをお勧めします。または、IDではなくオブジェクトが等しいかどうかを適切なoperator==とで比較しますoperator!=

あるいは、コピーコンストラクターとコピー代入以外で値が最初に構築されたときをIDで一意に識別したい場合(同じ「元の」のコピーであるすべてのオブジェクトがIDを共有するように)、それを行う方法は次のようになります。他のすべてのコンストラクターに新しい一意のIDを割り当て、それをデータメンバーに格納し、コピーコンストラクターとコピー代入演算子にコピーします。

新しいIDを取得するための標準的な方法は*、値を取得するたびにインクリメントするglobal[]カウンターを用意することです。これは、どのプログラムがクラスを使用するか(およびそれらがどのように使用するか)によっては、スレッドセーフにする必要がある場合があります。カウンターが十分に大きいタイプである場合、値はプログラムの特定の実行内で一意になります。

もう1つの方法は、128ビットの乱数を生成することです。理論的には満足のいくものではありませんが、まともなランダム性の原因を想定すると、衝突の可能性は、宇宙線によって引き起こされるデータ破壊などの避けられない理由でプログラムが失敗する可能性よりも大きくありません。オブジェクトのソースが広く分散している場合(たとえば、異なるプロセスまたは異なるマシン間で一意のIDが必要な場合)、ランダムIDはシーケンシャルIDよりも簡単です。マシンのMACアドレス、乱数、時間、プロセスごとのグローバル[ *]カウンター、PIDなど、考えて手にしたもの(または標準のUUID )を組み合わせて使用​​することを選択した場合は、 )。しかし、これはあなたのニーズにはやり過ぎかもしれません。

[ *]は厳密にグローバルである必要はありません。クラスのプライベート静的データメンバー、または関数の静的ローカル変数にすることができます。

于 2012-12-07T02:43:43.073 に答える