2011-01-21 4 views
1

나는 EventMgr 클래스에 리스너를 등록 할 템플릿 함수가있다. 그러나 리스너를 등록하면 링커에서 "오류 LNK2019 : 해결되지 않은 외부 기호"을 표시합니다.템플릿 함수 포인터로 링커 오류가 발생하는 이유는 무엇입니까?

전채 코드 : (청취자입니다)

class EventMgr { 

template< class T, class EvenT> 
void RegisterListener(T* listener, int EventType, void (T::*MemFunc)(EvenT*)); 
} 

SoundMgr이 이벤트에 등록하려고 :

SoundMgr::SoundMgr(void) 
{ 
    EventManager::GetInstance()->RegisterListener(this, 1, (&SoundMgr::handleBulletFired)); 
} 

나는 그것을 연결하지 않습니다 이유는 확실하지 않다. 참조 유형을 찾을 수없는 이유는 무엇입니까?

+0

코드를 형식화하십시오. – James

+1

링커 오류는 해결할 수없는 기호의 이름을 언급해야합니다. 상징의 이름은 무엇입니까? RegisterListener입니까? –

+0

1> SoundMgr.obj : 오류 LNK2019 : 해결되지 않은 외부 기호 "public : void __thiscall EventManager :: RegisterListener (클래스 Sound_Bulet_Fired *) (클래스 SoundMgr *, int, void (__thiscall SoundMgr :: *)) "(??함수 "public : __thiscallSoundMgr :: SoundMgr (void)"(?? 0SoundMgr @@ QAE @ XZ)에서 참조되는 $ RegisterListener @ VSoundMgr @@ VEvent_Bullet_Fired @@@ EventManager @@ QAEXPAVSoundMgr @@ HP81 @ AEXPAVEvent_Bullet_Fired @@@ Z @ * \t 템플릿 <클래스 T, 클래스 이벤트> \t 무효 개의 EventManager :: RegisterListener (T의 * 수신기, INT의 이벤트 유형, 무효 (T :: * MemFunc) (이벤트 : – brainydexter

답변

4

당신은 단순히 .H 파일에서 템플릿을 선언하고 구현 대신 .cpp 파일에서 C++ 컴파일러는 한 번에 하나 개의 컴파일 단위를 작동하기 때문에 다음이 당신이 얻을 것이다 오류 인 경우. 컴파일러가 방금 선언 한 템플릿 함수를 호출하는 코드를 찾으면 특정 인스턴스화가 다른 컴파일 단위에서 수행된다고 가정합니다 (컴파일러가 해당 함수의 .cpp 파일을 찾을 수있는 방법이 없습니다). .. 컴파일러는 한 번에 하나의 .cpp와 모든 포함 된 .h 만 볼 수 있습니다.

템플릿 매개 변수가 잘 알려진 목록에있는 경우 .cpp에서 프로그램에 필요한 모든 명시 적 구현을 ​​간단하게 요청할 수 있습니다. 템플릿 기능이 예를 들어

template<typename T> 
T foo(T x) 
{ 
    ... 
} 

방금 ​​필요할 것 알고 int foo(int);string foo(string); 다음 당신은 또한 두 줄을 추가 제공의 .H 단지 선언을 사용하는 것이 괜찮습니다 의 .cpp 말 : 당신이 전문성을 구축 할 작업에 대한 컴파일러를 말하는 것을 이렇게함으로써

template<> int foo(int); 
template<> string foo(string); 

. 나중에 다른 전문화 (예 : vector<int> foo(vector<int>))를 사용하면이 명시 적 인스턴스화를 템플릿의 .cpp 파일에 추가해야합니다.

그러나 예제에서 코드를 보면 어떤 종류의 이벤트가 정의되어 있는지 미리 알 수 없으므로이 명시적인 인스턴스화를 수행 할 수 없습니다.

다른 해결책은 구현에서 선언을 분리하는 대신 .h 파일에 전체 템플릿 구현을 넣는 것입니다. 이것은 더 많은 의존성을 도입 한 더 많은 구현 세부 사항을 노출해야하기 때문에 사소하지 않을 수 있습니다.

+0

나는 빈 몸을 줄 때에도 여전히 같은 오류가 발생합니다. – brainydexter

+1

코드 복사 및 붙여 넣기를 시도하고 누락 된 코드를 모두 추가하고 컴파일을 시도했습니다. 컴파일하는 코드가 게시 한 코드가 아닌지 ('EventManager' 또는'EventMgr'입니까?), 문제가 어디에 있는지 찾기가 어렵습니다. – 6502

+0

맞습니다. 모듈의 부실 사본을 사용하고있었습니다. 모든 템플릿 함수가 헤더에 본문이 있는지 확인한 후 코드를 정리하고 다시 작성하면 정상적으로 작동합니다. 감사! 따라서 원칙적으로 템플릿을 사용할 때마다 본문을 선언 할 때 본문을 정의해야합니까? – brainydexter

1

이것은 아마도 RegisterListener가 실제로 구현되지 않았 음을 의미합니다. 템플릿 함수이므로 헤더에 구현해야합니다.

헤더에서 다음을 시도해보십시오.

template< class T, class EvenT > 
void RegisterListener(T* listener, int EventType, void (T::MemFunc)(EvenT)) { } 
+0

나는 다음과 같이이 .cpp 파일에서 구현해야)) \t { \t \t lookup [EventType] = new FunctionHandler (listener, memFunc); \t} 또한이 오류를 주석으로 처리하고 헤더에 빈 본문을 만들면 여전히 같은 오류가 발생합니다. – brainydexter

+0

.cpp 파일로 구현하면 해당 cpp 파일 내에서만 사용할 수 있습니다. 머리글에 구현하십시오. – James

+0

헤더에 빈 몸체를 주더라도 여전히 오류가납니다. – brainydexter

관련 문제