2012-10-03 3 views
1

두 클래스가 추상 클래스에서 파생 된 다른 클래스에 대한 참조를 사용하는 멤버 함수로 클래스를 만들고 싶습니다. addElem()을 구현하지 않기 때문에 클래스 Container가 추상이라는 컴파일러 오류가 발생합니다.C++ 추상 클래스는 파생 클래스 매개 변수를 가져옵니다.

class Ielem 
{ 
public: 
    virtual void action() = 0; 
}; 

class Elem: public Ielem 
{ 
public: 
    void action() {}; 
    void extra() {}; 
}; 

class Icontainer 
{ 
public: 
    virtual void addElem(Ielem &elem) = 0; 
}; 

class Container: public Icontainer 
{ 
public: 
    void addElem(Elem &elem) { elem.extra(); }; 
}; 

int main(int argc, char* argv[]) 
{ 
    Elem e; 
    Container c; 
    c.addElem(e); 

    return 0; 
} 

Elem에 대한 참조는 Ielem을 참조하기 때문에 작동해야합니다. Container :: addElem을 Ielem에 대한 참조로 만들면 컴파일됩니다. 하지만 Container :: addElem()은 dynamic_cast를 사용하지 않는 한 Elem :: extra()를 호출 할 수 없습니다. 사용하고있는 내장 컴파일러에서는 사용할 수 없으며 유형이 안전하지 않은 일반 캐스트는 사용할 수 없습니다.

제안 사항?

+0

와 중간 추상 클래스를 만들 수 있으며,이 것 아마 그들 중 하나가 아닙니다. – Wug

+0

기본 클래스에 순수한'extra()'를 추가하지 않는 이유는 무엇입니까? – jrok

+0

제 실제 코드에서'extra()'는'Elem' 클래스의 특성과 관련이 있습니다. 다른 Ielem 구현에서는 의미가 없기 때문에 기본 클래스에 추가하여 구현하지 않아도됩니다. –

답변

0

문제는 단순히 가상 메서드가 오버로드하기위한 구체적인 메서드와 동일한 서명을 갖고 있지 않다는 것입니다. 그래서 컴파일러는 이것을 다른 함수로보고 void addElem(Ielem &elem)을 구현하지 않았기 때문에 불평합니다. 무엇을 보인다 것은 일반적인 디자인 가이드 라인, 예를 들어 준수하는 - 이것은 당신이 아마 그것은 다른 모든 제약 조건에 따라 달라집니다하지만 내가 무엇을 할 것이라고 생각

class Icontainer 
{ 
public: 
    virtual void addElem(Elem &elem) = 0; //Ielem -> Elem 
}; 

를 원합니까하지 않는 한 솔루션입니다 셔터 & Alexandreascu, 당신은이 작업을 수행 할 수있는있는 매우 특별한 상황이 있습니다 다음 전체 interface--

class Melem: public Ielem 
{ 
public: 
    // void action() {}; //Already have this form Ielem 
    void extra() = 0; 
}; 

class Icontainer 
{ 
public: 
    virtual void addElem(Melem &elem) = 0; 
}; 

class Container: public Icontainer 
{ 
public: 
    void addElem(Melem &elem) { elem.extra(); }; 
    //*Now* we're implementing Icontainer::addElem 
}; 
+0

여기의 문제는'Icontainer/Ielem '구현에'extra()'가 필요하다는 것입니다. 'extra()'는'Elem' 클래스에서만 의미가 있습니다. (또한'Melem'은'action()'을 구현하지 않고 순수한 가상의'Ielem'을 상속받지 않습니다.) –

+0

그러면 템플릿이 답이 될 것입니다. 재정의하려면 동일한 서명이 필요하며 기본 클래스에서 인식 할 수있는 파생 클래스에 인터페이스를 추가 할 수있는 방법이 없습니다. –

+0

다른 방법으로 중급 클래스를 사용하게되었습니다. –

1

그것은 라운드 잘못된 방법 : IcontaineraddElem 인수로 어떤Ielem 객체를 취할 수 있도록 지정 기본 클래스는하지만 파생 클래스에서 당신은 Elem에 동의합니다. 이것은 "더 좁은"유형이므로, 기본 클래스에 지정된 "Ielem 당신이 나에게 던졌습니다"라는 계약을 위반합니다.

여기 템플릿이 해결책이라고 생각합니다. 더 이상 기본 클래스가 필요하지 않습니다. 이런 식으로 뭔가 :

class Elem 
{ 
public: 
    void action() {}; 
    void extra() {}; 
}; 

template<typename ElemType> 
class Container 
{ 
public: 
    void addElem(ElemType &elem) { elem.extra(); }; 
}; 

int main(int argc, char* argv[]) 
{ 
    Elem e; 
    Container<Elem> c; 
    c.addElem(e); 

    return 0; 
} 

보너스로, 당신은 지금 extra() 기능이있는 유형 Container을 사용할 수 있으며, 그것은 단지 작동합니다.

+0

중급 클래스를 사용했기 때문에 해결책으로 다른 답을 골랐지 만 귀하의 대답은 내 코드가 컴파일되지 않은 이유에 대한 가장 좋은 설명이었습니다. 고맙습니다! –

관련 문제