과제를 하던 도중, 템플릿을 사용하여 vector 클래스를 만들고 있는데 .h 파일에서 정의를 하고 .cpp에서 구현을 하였더니 컴파일러가 링크 에러를 띄워주었다. (LNK1120)
이 문제점을 분석하고, 찾은 해결책을 정리해 보도록 할 것이다.
1. 템플릿 프로그래밍
- 템플릿은 코드의 재사용성을 높이기 위한 도구이다. 특히 STL에서 큰 힘을 발휘한다.
- 템플릿 프로그래밍의 동작 방식은
- 컴파일러가 컴파일 시에 알아서 만들어주는 기능이다.
- 즉 컴파일 도중에 템플릿 인스턴스에 대한 코드를 만들어 주게 된다.
- 예를 들어, 우리가 int res = Add<int>(3, 10); 할 때 컴파일러가 코드를 생성함
- 그래서 템플릿에 넣는 자료형의 가짓수에 비례하여, exe 파일도 증가하게 된다.
- 그 결과, 컴파일 타임은 느리지만 런타임 속도는 빠를 수 있게되고 코드의 중복이 적어진다.
- 템플릿 프로그래밍을 잘 쓰기 위해서는
- 최대한 제네릭 함수를 짧게 유지하고, 제네릭 부분이 아닌 것은 다른 함수를 만들어서 구현하는 방식이 좋다.
- 참고) 제네릭 함수는 T를 쓰는 함수
- 최대한 제네릭 함수를 짧게 유지하고, 제네릭 부분이 아닌 것은 다른 함수를 만들어서 구현하는 방식이 좋다.
- 템플릿 프로그래밍의 단점으로는 컴파일 도중에 다형성을 부여한다면, 읽기가 힘들어지고 유지보수가 어렵다는 점이 있다.
- 그래서 컨테이너에 적합한 방식이다.
2. 오류의 원인
- 결론부터 말하면, 템플릿은 일반화된 코드를 작성하는 방법이기 때문에, 구체적인 타입이 지정되기 전까지 실제로 존재하지 않는다는 것이다.
- 그래서 템플릿이 인스턴스화 되려면,
- 컴파일러가 템플릿의 정의를 알고있어야 하며,
- 그 정의를 사용해 컴파일 타임에 특정 타입에 대한 코드를 생성해야 한다.
- .h 파일에 선언하고 .cpp 에서 구현을 한다면
- 다른 소스파일(main.cpp 등)에서 템플릿 구현부에 접근을 할 수 없다.
- 왜냐하면,
- 템플릿은 컴파일 타임에 인스턴스화 되기 때문에 컴파일 타임에 해당 타입을 생성하기 위해 전체 정의와 구현을 같은 컴파일 타임에 볼 수 있어야 하기 때문이다.
- 우리가 main에서 템플릿 클래스 사용하기 전까지 컴파일러는 어떤 코드를 생성해야 할 지 모른다. (템플릿 구현부가 obj 파일에 저장되지 않는다.)
- 일반적인 클래스나 함수에서는 이 방식이 가능한 이유는
- 일반적인 함수나 클래스는 특정 타입에 구체화 될 필요가 없기 때문에, 구현부가 있는 .cpp가 컴파일 되면서 기계어 코드가 생성되어 링커가 참조할 수 있기 때문이다.
- 그래서 템플릿이 인스턴스화 되려면,
- 내가 이해한 대로 정리해보자면,
- 템플릿의 선언과 구현을 따로 둔다면,
- main 과 같은 다른 소스 파일에서 템플릿을 사용하는 코드를 발견하였을 때, 그 때 코드를 생성하게 되는데,
- 이때 #include "SimpleVector.h"와 같은 전처리기를 통해 .h 파일로 와서 코드를 생성하려고 한다.
- 그러나 .h 파일에 선언 밖에 없었기 때문에 구현을 찾으려고 하지만,
- 템플릿 특성상 구체적인 타입이 지정되지 않은 경우에는 코드가 생성되지 않으므로 구현된 내용을 찾지 못하고 링킹 에러가 발생하게 되는 것이다.
3. 해결책
- 템플릿 정의를 헤더파일에 포함하는 것 (가장 선호된다)
- .h 파일에 #include "~.cpp" 방식으로 구현 파일을 포함 (이 방식으로 해결 못해봄)
- .cpp 파일에서 구현부 작성 전 어떤 타입으로 쓸 것인지 명시적으로 타입을 구체화 해주기
- 아래처럼 쓸 수 있는데, 이러면 특정 타입을 사용할 때만 적합하므로 좋지 않다.
#include "SimpleVector.h"
template class SimpleVector<int>; //명시적 구체화
template <typename T>
SimpleVector<T>::SimpleVector()
{
...
}
'C++' 카테고리의 다른 글
const 키워드 (0) | 2024.12.31 |
---|---|
C++ TIL day 10 (0) | 2024.12.30 |
C++ 코딩 스탠다드 (2) | 2024.12.30 |
C++ TIL day 9 (3) | 2024.12.27 |
C++ TIL day 8 (0) | 2024.12.26 |