2012-04-03 2 views
2

STL과지도 반복자에서 필드를 받기 :함께 자신의 이름과 유형, 내가 특정 개체를 저장하는지도 컨테이너가

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"는 분명하지 않고 유지하기 어렵습니다. 나중에 필드가 변경되면 하나 이상의 필드를 지원하기 위해 모든 필드가 지원됩니다. 그래서 나는 다음과 같이 필드에 액세스하는 기능으로 변경할 것을 시도하고있다 :

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 수 있습니다.적어도 쌍을 사용하지 않으면 빠져 나갈 것입니다. 첫 번째, 두 번째 -> 두 번째 -> 두 번째 등 – 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

가장 큰 문제는 유지 보수 인 경우, 내가 하나로서 OBJTYPE 및 ObjBase *을 래핑하는 사용자 정의 클래스/구조체와 표준 : : 쌍을 대체 할 것이다.

  • 이 믹스에 새 필드를 쉽게 추가 할 수
  • 는 구조체의 필드에 액세스 쉽게 OBJTYPE 및 ObjPair
  • 은 OBJTYPE 및 ObjPair
  • 을 처리하는 클래스에 대한 게터/세터/다른 기능을 쓰기 쉽게
0

먼저 ObjType이 필수 항목인지 여부에 대해 직접 질문합니다. 목적이 쌍의 두 번째 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이 될 수 있기 때문입니다. 팩토리를 사용하여 새 인스턴스를 작성하는 데 사용됩니다. –