2013-04-21 7 views
0

이의 우리가 같은 컬렉션 클래스가 있다고 가정하자 B는 추상 클래스와재정의 함수 매개 변수/

doSomethingWithAllObjects(); 

의 특정 행동이

class CCollection { 

public: 
    void add(B& b); 
    void remove(B& b); 
    void doSomethingWithAllObjects(); 

protected: 
    std::vector<B*> bs; 

} 

가 B의 구체적인 유형에 따라 달라

, 전화를 그것은 C.

CCollection을 유도하고 방법을 알려줄 수있는 방법이 있습니까

add(B b); 
remove(B b); 

파생 형식을 수락 하시겠습니까?

class D : A{ 
public: 
    void add(C c); 
    void remove(C c); 
    void doSomethingWithAllObjects(); 
private: 
    std::vector<B*> bs;  
} 

를하거나 유도 거의 100 %를 동일

template<class T : B> 
class C { 
    ...//do lots of stuff 
} 

같은 일반적인 javaish가 구성 :

는이 같은 방법을 재정의 같은 것을 생각했다. 그러나 당신은 B의 다른 파생어를 섞어서는 안됩니다.

나는 이미 템플릿 클래스를 특정 유형으로 제한하는 것이 불가능하지만 B의 모든 파생에 대해 전체 클래스를 작성하는 것을 피할 수있는 방법이 있어야합니다. 요점은, 나는 B에 정의 된 기능이 필요합니다, 그래서 난 그냥 바로 CCollection에 대한 권리 유형을 넘겨 내가 다른 프로그래머를 가정 할 수 물론 간단한 템플릿

template<class T> 
class B{ 
    .... 
} 

을 사용할 수 있지만,이 정신이 될 수 없습니다. 내가 원한 것은 다른 프로그래머에게 단 하나의 유형의 Bs를 추가하도록 강제하는 것입니다. 당신이 CB의 서브 클래스가 아닌 경우 Collection<C>를 인스턴스화하려고하면

+0

스택 오버플로에 오신 것을 환영합니다! 내가 당신의 질문을 올바르게 읽는다면 근본적인 디자인 문제가있는 것 같다. 'virtual' 함수는 * runtime *에서 행동을 결정할 수있게합니다. 그리고 그 매개 변수의 유형을 변경하는 것은 런타임 조건이 알려지기 전에 컴파일 타임에 적용되는 것입니다. 컴파일시에 무엇을 시행하기를 희망하십니까? –

+0

파생 된 형식을 수락 하시겠습니까? 기본 클래스 추상 클래스가 아닌가? 당신은 그것의 객체를 선언 할 수 없습니다. 어떻게 추가하고 제거 할 수 있습니까? 내가 여기서 뭔가를 놓치고 있니? – stardust

+0

값 매개 변수'add (B b)'를 벡터'std :: vector '에 저장하는 포인터로 변환하는 방법을 모르겠다면 취할 수있는 유일한 주소는 함수의 끝 'add()' –

답변

0

나는 확실하지 않다하지만 난 당신이 간단한 템플릿 비회원 형 기능에 대한 loooking 생각합니다. 템플릿 함수를 사용하여 유형이 일치하는지 확인할 수 있습니다. 상속을 기반 형 공제를하지 않기 때문에

template<typename T> 
void global_adder(const T& cl, const T& toadd) { 
    cl.add(toadd); 
} 
  • ,이 A가 등등 C에 B 또는 B에 추가되지 않았는지 확인합니다. 추가하려면 두 args가 모두 같은 유형이어야합니다. 아무것도 더.

  • 클래스 메서드는 기본 클래스에만 유지합니다. protected으로 만들고이 함수를 friend으로 추가하십시오.

  • 당신은 지금 아무도 (특정 클래스에 다른 유형을 추가 할 수 없습니다 ) 다른 곳 에서 a.add 또는 b.add를 호출 할 수없는 것입니다 그런 식으로.

  • 요소를 추가하거나 제거하는 유일한 방법은 유형이 일치하는지 확인하는 템플릿 함수를 사용하는 것입니다.

+0

완벽하게 작동합니다. 고맙습니다! –

-1

당신은

class BaseCollection { 
    public: 
    void doSomethingWithAllObjects(); 
    protected: 
    void addInternal(B* b); // consumes the element 

    std::vector<B*> bs; // or better use vector<shared_ptr> for reference count 
}; 

template <typename C> 
class Collection : public BaseCollection { 
    public: 
    void add(const C& c) { 
     C* my_copy = new C(c); // suppose we have a copy constructor 
     addInternal(my_copy); 
    } 
}; 

같은 추상 기본 컬렉션 클래스를 만들 수 있습니다, 당신은 컴파일 오류가 발생합니다. 내가 제대로 이해하면

+0

컬렉션에 포인터를 전달하지 마십시오. 당신이 소유권을 가지고 있지 않다는 것을 나타내는 참조를 전달하거나 (그러면 bs에 저장을위한 포인터로 변환한다). 또는 소유권을 취하고 있음을 나타내는 스마트 포인터를 전달합니다 (스마트 포인터 유형으로 정의 됨). –

+0

벡터 은 좋지 않습니다. 소유권의 상징을 혼합하고 있습니다. 저장 기준을 정의 할 수있는 소유권 표현을 정의하십시오. –

+0

이것은 정확히 내가 피하려고하는 것입니다. 왜냐하면 모든 새로운 파생에 대해 중복 된 코드가 많기 때문입니다. 방금 예제를 게시했습니다. 내 실제 컬렉션 클래스는 조금 더 복잡합니다 ;-) –