2013-06-14 3 views
6

다음은 내가 가지고있는 문제를 재현하는 코드입니다. Base 클래스는 가상 함수가 foo 인 템플릿 클래스입니다. foo에는 전달 된 인수를 추가하는 기본 구현이 있습니다.C++ 템플릿 클래스 가상 함수 오버로드

SimpleDerivedBase에서 파생되며 std::string으로 전문화됩니다. SimpleDerived은 가상 Base<T>::foo() 기능을 오버로드합니다. 이 클래스는 main에서 호출 될 때 잘 컴파일되고 foo 출력을 예상대로 컴파일합니다.

#include <iostream> 

template<class T> 
struct Base 
{ 
    virtual void foo(T val) 
    { 
     T local = val + val; // THE OFFENDING LINE OF CODE 
     std::cout << "Base" << std::endl; 
    } 
}; 

struct SimpleDerived : public Base<std::string> 
{ 
    virtual void foo(std::string val) 
    { 
     std::cout << "SimpleDerived" << std::endl; 
    } 
}; 

struct SimpleObject 
{ 
    int value; 
}; 

struct ComplexDerived : public Base<SimpleObject> 
{ 
    virtual void foo(SimpleObject val) 
    { 
     std::cout << "ComplexDerived" << std::endl; 
    } 
}; 

int main(void) 
{ 
    Base<int> base; 
    base.foo(2); 

    SimpleDerived simpleDerived; 
    simpleDerived.foo("hello world"); 

    SimpleObject object; 
    ComplexDerived complexDerived; 
    complexDerived.foo(object); 

    return 0; 
} 

ComplexDerived 사용자 정의 구조체 SimpleObject와 함께 전문 Base에서 유래. ComplexDerivedfoo에도 오버로드됩니다. 그러나 이것이 문제의 근원입니다. 나는 이것을 컴파일하려고하면 내가 얻을 :

quicktest.cpp: In member function ‘void Base<T>::foo(T) [with T = SimpleObject]’: 
quicktest.cpp:47:1: instantiated from here 
quicktest.cpp:8:19: error: no match for ‘operator+’ in ‘val + val’ 

을 분명히 어떤 연산자는 "+"SimpleObject을 위해 존재하지 않는다. 하지만 여기에 내 혼란이있다. 컴파일러는 Base<SimpleObject>::foo을 구현해야한다. 왜냐하면 이것이 ComplexDerived에서 상속받은 것이기 때문이다. 그러나 절대로 Base<SimpleObject>::foo을 사용하거나 전화하지 않습니다. 그래서 컴파일러는이 기본 클래스 함수를 생성하려고합니까? 는 C++ 11 표준 지정의

+0

컴파일러가 기본 클래스에서 가상 함수를 인스턴스화하려고 할 때 대답을 확인하는 것처럼 보일 수도 있기 때문에 템플릿 순수화를 사용하여 문제를 해결할 수 있습니다. – kloffy

답변

9

단락 14.7.1/10 :

내재적 기능 템플릿 멤버 템플릿이 아닌 가상 멤버 함수 구성원 클래스를 인스턴스화한다 구현 , 또는 인스턴스 생성을 필요로하지 않는 클래스 템플릿의 정적 데이터 멤버. 가상 멤버 함수가 인스턴스화되지 않으면 구현시 암시 적으로 클래스 템플릿의 가상 멤버 함수 을 인스턴스화할지 여부는 지정되지 않습니다. [...]

즉,이 경우의 동작은 구현에 따라 다릅니다.

이론 컴파일러 (함수 호출이 참조 또는 포인터를 통해 발생하지 않기 때문에) foo()의 기본 클래스의 구현에 대한 호출이 적 호출되지 않는다는 것을 파악하고 인스턴스화 피할 수 있지만,이 행동은 표준에 의해 위임되지 않습니다.

+0

감사합니다. Andy! 그냥 fyi, 나는 g ++ (우분투/Linaro 4.6.3-1ubuntu5) 4.6.3을 사용했다. – user2130260

+0

@ user2130260 : OK, 도움이 되니 기쁩니다 :) –