[Software]/Programming Tips2009. 3. 27. 09:23

/// 질문

템플릿을 클래스 설계시

//node.h
#ifndef __NODE_H__
#define __NODE_H__

template< class NODE >
class Node
{
public:
Node( const NODE & );

private:
NODE data;
Node<NODE> *prevPtr;
Node<NODE> *nextPtr;
};

template< class NODE >
Node< NODE >::Node( const NODE &value )
{
data = value;
prevPtr = 0;
nextPtr = 0;
}

#endif

이런식으로 .h 파일에 멤버 함수 까지 다 정의하면 컴파일시 에러가 나지 않습니다.
보통 짜는 형식으로
요까지는 node.h 파일에 넣고

template< class NODE >
class Node
{
public:
Node( const NODE & );

private:
NODE data;
Node<NODE> *prevPtr;
Node<NODE> *nextPtr;
};

//node.cpp
#include "node.h"
template< class NODE >
Node< NODE >::Node( const NODE &value )
{
data = value;
prevPtr = 0;
nextPtr = 0;
}

이렇게 .h와 .cpp를 분리하면 아래와 같은 에러가 발생합니다.
main.obj : error LNK2001: unresolved external symbol "public: __thiscall Node<int>::Node<int>(int const &)" (??0?$Node@H@@QAE@ABH@Z)
Debug/DList.exe : fatal error LNK1120: 1 unresolved externals
Error executing link.exe.

도대체 왜 에러가 나는지 또 에러를 어떻게 처리해야 되는지 모르겠습니다.
한수 가르쳐 주세요

 

/// 답변

클래스 템플릿을 만들때는 해당 클래스 템플릿을 사용하는 파일에서 클래스 템플릿의 모든 정의 부분이 보여야 합니다.

또한 클래스 템플릿의 정의 뿐만이 아니라 호출하는 멤버 함수들의 정의 역시 모두 보여야 합니다. 즉, #include 파일에 들어가 있어야 한다는 뜻입니다.

따라서 보통 클래스 템플릿을 만들때는 멤버 함수들을 따로 .cpp파일에 정의하지 않고 .h파일에 같이 정의해 놓습니다.

일반적인 클래스나 함수의 경우 별도의 파일에서 컴파일 과정을 통해서 오브젝트 파일을 만들고 이것을 가지고 링크가 되지만, 함수 템플릿이나 클래스 템플릿은 컴파일 과정에서 해당 문법 체크과정 외에 실제 사용 시 넘겨진 타입 파라미터를 이용해서 구체화(instantiation)과정을 거치게 되는데 이 때 사용되는 모든 정의 부분이 컴파일되는 파일에서 모두 #include 등을 통해 명시적으로 보여야 하기 때문입니다.

그러므로 질문하신 예의 경우 Node 클래스 템플릿을 사용하는 main.cpp에서 Node<int> 객체를 생성할 때 컴파일러는 Node 클래스 템플릿의 정의 부분을 직접 참조할 수 있어야 합니다.

하지만 node.cpp 파일은 main.cpp에서 #include 되어있지 않으므로 오브젝트 코드를 제대로 만들 수 없는 것입니다.


 


Posted by 바트정