Coding Memo

VS 템플릿 클래스 사용 시 빌드 오류 (LNK2019, LNK1120) 본문

Language/C++

VS 템플릿 클래스 사용 시 빌드 오류 (LNK2019, LNK1120)

minttea25 2023. 1. 7. 17:33

C++에서 자신이 사용할 클래스를 템플릿화 시켜서 코드를 작성했다고 하자.

다음과 같은 코드가 있다. (별 의미가 없는 클래스이다)

#pragma once

template<typename T>
class MyData
{
public:
	int size() { return _data.size(); }
	void addData(T t) { _data.push_back(t); }
	vector<T> data() { return _data; }
private:
	vector<T> _data;
};

이 클래스를 main함수가 포함되어 있는 파일에 추가하거나

다음과 같이 헤더파일을 include하여 main에서 사용하면 문제가 없다.

오류 없이 '10'이 제대로 출력되고 프로그램이 종료될 것이다.

#include "MyData.h"

int main()
{
    MyData<int> data;

    data.addData(10);

    cout << data.data()[0] << endl;

    return 0;
}

 


이번 케이스는 내가 실제로 경험했던 오류이다... (단순히 LNK2019오류가 왜 뜨는지에 중점만 두고 해결방법을 찾다가 해결하는데 오래 걸렸다.)

 

만약 헤더파일과 cpp파일(소스 파일)을 별도로 나눠서 관리할 경우 위와 같은 코드를 빌드하면 오류가 발생한다!

#include "MyData.h"
int main()
{
    MyData<int> data;

    data.addData(10);

    cout << data.data()[0] << endl;

    return 0;
}
MyData.h MyData.cpp
#pragma once

template<typename T>
class MyData
{
public:
int size();
void addData(T t);
vector<T> data();
private:
vector<T> _data;
};
#include "MyData.h"

template<typename T>
int MyData<T>::size()
{
return _data.size();
}

template<typename T>
void MyData<T>::addData(T t)
{
_data.push_back(t);
}

template<typename T>
vector<T> MyData<T>::data()
{
return _data;
}

 

 

왜 오류가 발생한 것일까?

 

그 이유는 main 함수에서 그 클래스를 사용하려고 할 때, 템플릿 클래스에 대한 메소드를 찾지 못하기 때문이다.

 

아니 (템플릿 클래스가 아닌)다른 클래스들 또한 마찬가지로 헤더와 소스파일을 나눠서 관리하는 데도 문제가 없었는데 왜 여기서만 일어날까?

 

템플릿 클래스는 다른 일반적인 클래스들과 달리 빌드 시, 미리 컴파일 되지 않고, 컴파일 중 코드 상에서 사용할 때 typename으로 들어온 T에 대한 템플릿 클래스를 생성하게 된다. 타입 T에 어떤 타입이 들어올 지 알 수 없다. 따라서 사용할 때에 들어온 T 타입에 맞는 클래스를 생성한다.

 

즉, main함수에서 볼 때, MyData<int> data; 선언 시점에 int 타입에 대한 MyData 클래스를 오브젝트로 생성하게 되는 것이고, 만들어진 int 타입에 대한 클래스의 메소드가 헤더 파일이 아닌 cpp 파일에 포함되어 있기 때문에 cpp파일 또한 include를 해주어야 문제 없이 빌드 할 수 있다. (생성될 때 헤더파일과 소스 파일을 모두 참조해야 한다!)

#include "MyData.h"
#include "MyData.cpp"

int main()
{
    MyData<int> data;

    data.addData(10);

    cout << data.data()[0] << endl;

    return 0;
}

 

참고: VS에서 템플릿 클래스의 메서드를 헤더에서 선언 후,  alt+enter로 정의를 자동 생성하게 되면 inline 함수로 생성되게 된다. 이 이유는 특정 템플릿 타입에 의해서 실행 될 때 만들어져서 속도가 느려지기 때문에 inline 함수로 자동으로 선언하도록 하게 한 것인것 같다. (그러나 요즘 컴파일러는 성능향상이 예상되는 함수들을 모두 자동으로 inline으로 한다고 한다...)


정리

템플릿 클래스를 헤더 파일과 소스파일을 나누어 사용할 시에 헤더 파일과 소스 파일, 2개의 파일 모두 include하여 사용하자.

'Language > C++' 카테고리의 다른 글

[C++] 여러가지 출력 방법 (스트림 서식화)  (0) 2023.07.11
C++ 리터럴 표기법 및 팁  (0) 2023.01.07
소켓 IO 모델 장단점 정리  (0) 2022.11.29
volatile 전역변수 사용 - 쓰레드  (0) 2022.09.06
volatile 변수  (0) 2022.08.19