2010-03-04 3 views
1

안녕! 누구든지 아래 코드에서 "chug(derlist);"줄을 어떻게 만들 수 있는지 알고 있습니까?C++ : 기본 클래스의 컨테이너를 기대하는 함수에 파생 클래스의 컨테이너를 전달하려면 어떻게해야합니까?

#include <iostream> 
#include <list> 
using namespace std; 

class Base 
{ 
public: 
    virtual void chug() { cout << "Base chug\n"; } 
}; 

class Derived : public Base 
{ 
public: 
    virtual void chug() { cout << "Derived chug\n"; } 
    void foo() { cout << "Derived foo\n"; } 
}; 

void chug(list<Base*>& alist) 
{ 
    for (list<Base*>::iterator i = alist.begin(), z = alist.end(); i != z; ++i) 
     (*i)->chug(); 
} 

int main() 
{ 
    list<Base*> baselist; 
    list<Derived*> derlist; 

    baselist.push_back(new Base); 
    baselist.push_back(new Base); 
    derlist.push_back(new Derived); 
    derlist.push_back(new Derived); 

    chug(baselist); 
    // chug(derlist); // How do I make this work? 

    return 0; 
} 

나는이 기본적으로 필요로하는 이유는, 내가 만 복잡한 객체에 대한 하나 또는 두 개의 가상 함수를 걱정 특정 기능에 전달해야 매우 복잡한 객체의 컨테이너가 있습니다.

짧은 답변은 "할 수 없다"는 것을 알고 있습니다. 사람들이이 문제를 해결하기 위해 사용하는 속임수/숙어를 찾고 있습니다.

미리 감사드립니다.

답변

5

귀하의 질문은 이상합니다. 주제는 "다형성을 잃지 않고 컨테이너에 항목을 넣는 방법"을 묻습니다. 컨테이너의 항목은 다형성을 잃지 않습니다. 기본 유형의 컨테이너 만 있으면 모든 것이 작동합니다.

샘플에서는 "자식 포인터의 컨테이너를 기본 포인터의 컨테이너로 어떻게 변환합니까?"라고 묻는 것 같습니다. - 그 대답은 당신이 할 수 없다는 것입니다. 하위 포인터는 기본 포인터로 변환 할 수 있으며 자식 포인터의 컨테이너는 변환 할 수 없습니다. 관련없는 유형입니다. shared_ptr 이 shared_ptr로 변환 될 수 있지만 그 작업을 수행하는 데 특별한 마법이 있기 때문에주의하십시오. 컨테이너에는 그러한 마술이 없습니다.

한 대답은 칙칙 푹푹하는 소리를 템플릿 기능을하게하는 것입니다 (면책 조항 : 나는 컴파일러 컴퓨터에없는, 그래서 나는이 컴파일 시도하지 않은) :

template<typename C, typename T> 
void chug(const C<T>& container) 
{ 
    typedef typename C<T>::iterator iter; 
    for(iter i = container.begin(); i < container.end(); ++i) 
    { 
     (*i)->chug(); 
    } 
} 

은 다음 칙칙 푹푹하는 소리가을 사용할 수 있습니다 모든 유형의 컨테이너, 포인터의 컨테이너이며 chug 메소드가있는 경우.

+0

안녕하세요, Terry, 더 정확한 답변을 드리겠습니다. 내가 아래에 아무것도 모르겠어 함께 갈거야 은) ((목록 :: 반복자 I = alist.begin에 대한 \t 템플릿 \t 무효 칙칙 푹푹하는 소리 (목록 및 alist) \t { \t을 컴파일 버전입니다 , z = alist.end(); i!= z; ++ i) \t (* i) -> chug(); \t} 그리고 작동합니다. 다형성이 아니기 때문에 완벽한 해결책은 아니지만 필요한만큼 효과적입니다. Base에서 파생 된 사람이 추가 코드를 작성하지 않아도되는 다른 솔루션은 생각할 수 없습니다. – Kyle

1

포인터로 저장 (boost :: shared_ptr이 인기있는 옵션)하거나 내부적으로 포인터를 저장하는 Boost ptr_containers를 사용하지만 바깥쪽에는 (물론 완전히 자동화 된 삭제) 멋진 API를 제공합니다. 용기의

#include <boost/ptr_container/ptr_vector.hpp> 

boost::ptr_vector<FooBase> foos; 
foos.push_back(new FooDerived(...)); 
foos[0].memberFunc(); 

다형성 전환은 그래서 항상 함수 자체에 ptr_vector < 자료 > &과 내리 뜬을 통과, 단순히 불가능합니다.

+0

+1 for ptr_container. 정말 훌륭한 도서관입니다. – rlbond

0

chug 템플릿 매개 변수를 Base* 유형으로 캐스팅 한 템플릿 함수를 만든 다음 chug을 호출 할 수 있습니다.

0

기본 및 파생 형식에 대한 인스턴스를 가질 수 있도록 템플릿 기반 함수를 왜 만들지 않습니까?

또는 더 나은 해결책을 얻으려면 std::for_each을 사용할 수 있습니다.

관련 문제