2013-10-09 5 views
1

원하는 작업 : 가능한 한 일반적인 일반 템플릿으로 정의 된 간단한 저장소 클래스. 이 클래스에서 다른 클래스를 파생시킬 수 있다면 아무 것도 받아 들일 수 없으므로 int (알고리즘은 여기에서 관련이 없습니다)으로 변환하고 기본 클래스에 저장합니다.다른 서명을 가진 다형성과 오버로드 된 함수

그러나 이것은 예상대로 작동하지 않습니다.

template<typename T> 
class A { 
    public: 
    void f(T& foo) { } 
}; 

class B : public A<int> { 
    public: 
    template<typename T> 
    void f(T& foo) { } 
}; 

int main() { 
    A<int>* ptr = new B; 
    ptr->f("foo"); 
    delete ptr; 
    return 0; 
} 

은 물론,이 작동하지 않습니다 다음은 최소한의 테스트 내가 쓴 경우이다

[email protected]:~/Workspace/Test/src$ icpc -o Test Test.cpp 
Test.cpp(16): error: a reference of type "int &" (not const-qualified) cannot 
be initialized with a value of type "const char [4]" 
    ptr->f("foo"); 
     ^

compilation aborted for Test.cpp (code 2) 

는 B 클래스에서 메소드 정의를 사용하도록 컴파일러에 강제 할 수있는 방법이 있습니다, 또는 이건 정말 나쁜 생각인가요?

은 -

편집 : 상속 공개.

답변

3

먼저 @GermanDiago가 지적한 것처럼 개인 상속을 사용 중이므로 "기본 클래스에 액세스 할 수 없음"오류가 발생합니다. 공개적으로 A<int>에서 파생되도록 B을 변경하십시오.

그래도 문제가 해결되지는 않습니다. 이름 조회는 정적 유형을 기반으로합니다. A<int>에 대한 포인터가 있으면 해당 포인터를 통해 멤버에 액세스하면 A<int>의 멤버 만 나타납니다. 내가 제대로 질문을 이해한다면, 이것은 당신이 정말로 원하는 것이 아니다, 물론

int main() { 
    B* ptr = new B; 
    ptr->f("foo"); 
    delete ptr; 
    return 0; 
} 

: 사용자가 입력 B를 통해 액세스 할

B의 구성원을 볼 수 있습니다. 대신 Curiously Recurring Template Pattern을 볼 수 있습니다. 물론

template <class T, class Derived> 
class A { 
    public: 
    template <class U> 
    void f(U& bar) { 
     static_cast<Derived*>(this)->f(bar); 
    } 

    void f(T& foo) { 

    } 
}; 


class B : public A<int, B> 
{ 
    public: 
    template <class T> 
    void f(T &foo) { 
     //will be called from A's f(U&) 
    } 
}; 


int main() { 
    A<int, B>* ptr = new B; 
    ptr->f("foo"); 
    delete ptr; 
    return 0; 
} 

Live example

,이 A의 유형의 일부가되어 가고 B의 단점이있다. 나는 여전히 컴파일 타임을 유지하면서 이것으로부터 벗어나는 방법이 있다고 생각하지 않는다.

+0

도움이되는 설명 주셔서 감사합니다. 분명히, 나는 조금 더 생각해야 할 것이다 ... – Pierre

1

당신은 공공 상속을 사용해야합니다

class B : public A<int> { 
    //... 
} 

-IS는 C++의 관계는 공공 상속을 통해입니다. 개인 상속은 현재 사용중인 것입니다.

+0

참이지만 여전히 'B :: f'를 'A'에 대한 포인터를 통해 호출 할 수 없습니다. – Angew

+0

감사합니다. 단순한 실수, 방금 고쳤습니다. 여전히 주요 문제는 해결되지 않습니다./ – Pierre