2012-04-03 7 views
2

からフィールドを取得:は、私は一緒に自分の名前とタイプして、特定のオブジェクトを格納するためのマップ・コンテナを持つSTLのmapのイテレータ

typedef std::map<std::string, std::pair<ObjType, ObjBase*> > ObjContainer; 

しかし、コードの多くの部分で、このような構造があります。

ObjContainer::iterator it = mObjContainer.find(name); 
if (it != mObjContainer.end()) { 
    if (it->second.second) { 
     it->second.second->setObj2Default(); 
     delete it->second.second; 
     it->second.second = 0; 
    } 
} 

明らかに、多くの "it-> second.second"はあまり明確ではなく、維持不能です。 将来変更された場合、たとえば、もう1つのフィールドをサポートするために、すべてが破損します。 だから、私はこのように、フィールドにアクセスするための関数でそれらを変更しようとしています:

ObjBase*& getObjPtr(ObjContainer::iterator it) { 
    return it->second.second; 
} 

は同様に、getObjNameとgetObjType機能します。

また、これらのフィールドを返すイテレータを持つことがより明確になることを私に示唆された。

it.objPtr(); 
it.objName(); 
it.objType(); 

しかし、私はSTLのイテレータは右、これらの機能を持つように継承されるべきではないと思いますか?マップのラッパーを作成し、それらの関数で独自のイテレーターを作成する以外は、他の方法はありません。

だから、最も適切な選択肢は何ですか?私が見ていないこの問題を解決する他の方法はありますか?

+2

は、なぜあなたは単に構造体を使用していないし、コード内second.second

typedef std::map<std::string, ObjBase*> ObjContainer; 

これ以上ありませんペアの代わりにあなたのフィールドにあなたが望むように名前を付けますか? – Spidey

+0

@ Spidey:ライブラリに完全にサービス可能なクラスが付属している場合、なぜ独自のクラス定義をロールバックするのですか? –

+0

あなたはacessorsとwrap'emすることができます。少なくともpair.first、pair.second、pair-> second-> secondなどを使用しないで離れることになります。 – Spidey

答えて

2

私は、ポインタ(または参照)のローカルコピーを作成したい - それはおそらく、とにかくアウトに最適化されます:

ObjContainer::iterator const it = mObjContainer.find(name); 
if (it != mObjContainer.end()) 
{ 
    ObjBase * & p = it->second.second; 
    if (p) { p->foo(); delete p; p = NULL; } 
} 
0

は、構文を簡素化するための参照を使用してください。

ObjContainer::iterator it = mObjContainer.find(name); 
if (it != mObjContainer.end()) { 
    std::pair<ObjType, ObjBase*> & ref = it->second; 
    if (ref.second) { // ... 
4

最大の問題は、保守性がある場合、私は1つとしてOBJTYPEとObjBase *をラップするカスタムクラス/構造体とはstd ::ペアを置き換えます。

  • それはそれはOBJTYPEとObjPair
  • を扱うクラスのゲッター/セッター/他の関数を書くのは簡単だ構造体のフィールドOBJTYPEとObjPair
  • にアクセスするのは簡単ですミックスで
  • を新しいフィールドを追加するのは簡単です
0

私は最初にObjTypeが必須かどうかについて自分自身に疑問を呈しました。 ペアの2番目のObjBase *パラメータで実際にどのクラスのクラスが指し示されているのかを調べたい場合は、dynamic_castを使用してペアを削除します。

ObjContainer::iterator it = mObjContainer.find(name); 
if (it != mObjContainer.end()) { 
    if (it->second) { 
     it->second->setObj2Default(); 
     delete it->second; 
     it->second = NULL; 
    } 
} 

そして、あなたは、オブジェクトの実際の型をテストする必要がある場合:

ObjContainer::iterator it = mObjContainer.find(name); 
if (it != mObjContainer.end()) { 
    if (ChildObj* p_Child = dynamic_cast<ChildObj*>(it->second)) { 
     // Work on p_Child... 
    } 
} 
+0

いいえ、ObjTypeが必要な場合があります。ObjBase *がnullになることがあり、ObbTypeがファクトリを使用して新しいインスタンスを構築するために使用されます。 –

関連する問題