2013-08-19 2 views
0
void Library::addKeywordsForItem(const Item* const item, int nKeywords, ...) 
{ 
    // the code in this function demonstrates how to handle a vararg in C++ 

    va_list  keywords; 
    char  *keyword; 

    va_start(keywords, nKeywords); 
    for (int i = 0; i < nKeywords; i++) 
    { 
     keyword = va_arg(keywords, char*); 
     ((Item*)const_cast<Item*>(item))->addKeyword(string(keyword)); 

     ItemSet* itemSet = keywordItems[string(keyword)]; 
     if (itemSet == NULL) 
     { 
      itemSet = new ItemSet(); 
      keywordItems[keyword] = itemSet; 
     } 
     bool isNull = (itemSet == NULL) ? true : false; 
     itemSet->insert(((Item*)const_cast<Item*>(item))); 
    } 
    va_end(keywords); 
} 

const ItemSet* Library::itemsForKeyword(const string& keyword) const 
{ 
    return keywordItems[((string)const_cast<string&>(keyword))]; 
} 

위의 코드에서 첫 번째 방법은 예상대로 작동합니다. 두 번째 방법은 없으며, 오류가 표시 @ "["C++ 맵 [] 연산자를 찾을 수 없음

더 연산자 "[]"이 피연산자 피연산자 타입이 일치하지 : CONST StringToItemSetMap는 [STD : 문자열]

StringToItemSetMap 인 지도의 typedef입니다. 로컬 문자열 변수를 만들뿐 아니라 다른 캐스트도 시도했지만 행운은 아닙니다. keywordItems [string ("test")]; 두 번째 방법에서는 작동하지 않지만 첫 번째 방법에서는 작동합니다. 제가 놓친 게 있을까요?

편집 :지도 :: 연산자 [] 아니지만

const ItemSet* Library::itemsForKeyword(const string& keyword) const 
{ 
    std::map<std::string, ItemSet*>::const_iterator it = keywordItems.find(keyword); 
    if (it != keywordItems.end()) 
    { 
     return it->second; 
    } 
    return NULL; 
} 

로서

는 응답 중 지적하고, 문제는 두 번째 방법 인 CONST이었다.

+1

'keywordItems [ "test"]'를 사용해 보셨습니까? – Dukeling

+3

내가 왜'const_cast'를하고,'C 스타일'을'string'으로 캐스팅했는지 물어봐야할까요? – cHao

+2

'char *'를 맵 키로 사용하지 마십시오. –

답변

4

오버라이드 된 operator[]을 사용하고 있습니다. 기본 맵에 const가 아닌 액세스 권한이 있어야합니다. 요청 된 키 위치에 항목이 없으면 새 항목이 추가됩니다. 귀하의 경우 NULL 포인터 (이유에 대한 이유가없는)를 추가합니다. 귀하의 회원 함수는 const로 선언되어 있으므로지도를 수정할 수 없습니다.

지도를 mutable (권장하지 않음)으로 선언하거나 반복자 검색을 사용하고 검색 결과가 keywordItems.end() 인 경우 NULL을 반환하십시오. 그렇지 않으면 반복자의 객체 (it->second)를 반환합니다.

const ItemSet* Library::itemsForKeyword(const string& keyword) const 
{ 
    std::map<std::string, ItemSet*>::const_iterator it = keywordItems.find(keyword); 
    if (it != keywordItems.cend()) 
     return it->second; 
    return nullptr; 
} 

참고 : 나는 것 강하게 조언을 직접 개체 또는지도 객체 컨텐츠 (예 : std::shared_ptr<ItemSet> 등) 적어도 스마트 포인터를 사용하여. RAII : 저녁 식사는 뭐지?

+0

답해 주셔서 감사합니다. 지역 코드를 작업 코드로 편집했습니다. ItemSet *을 const로 동적으로 캐스팅했습니다. 나는 그것이 왜 필요한지 잘 모르겠습니다. 어쩌면 간단히 설명해 주시겠습니까? –

+0

또는'.at()'을 사용할 수 있습니다. C++ 11 지원이 필요합니다. – DanielKO

+0

@ jM2.me지도가 보유하고있는 것이 무엇인지 알 수 없습니다. 그것은'ItemSet *'입니다. 그러면 필요하지 않습니다. 일부 기본 클래스 포인터 유형 인 경우 제대로 반환 유형으로 캐스팅해야합니다. 이것은 C++입니다. 실제로 C 스타일 캐스팅을 사용하지 마십시오. 필자의지도가 내 예제의 반복자 선언에서와 같이 가정 된 것으로 가정 해 보았습니다. 희망이 옳다. – WhozCraig