클래스 템플릿도 멤버함수를 클래스 외부에 정의하는 것이 가능하다.
외부에 정의할 때 클래스이름<T>가 의미하는 바는 다음과 같다.
- "T에 대해 템플릿화 된 (클래스이름) 클래스 템플릿이다."
즉, 이것은 일반 클래스가 아니고 클래스 템플릿이라는 뜻으로 생각하면 된다.
또한 클래스 템플릿의 정의와 함수의 정의가 완전히 별개이기 때문에 각각에 대해서 문자 T가 무엇을 의미하는지 설명해야 한다.
# 일반적인 클래스의 정의아 마찬가지로 매개변수의 디폴트 값은 클래스 템플릿 내에만 표시한다.
★ 템플릿 클래스는 일반적인 클래스를 대상으로 해 왔던 동일한 방식으로 파일을 나누고 컴파일을 해보면 문제가 발생한다.!!!
파일을 나눌 때의 고려할 사항
※ 컴파일은 파일단위로 이루어진다.
main 함수가 정의된 소스파일이 컴파일 될 때, 컴파일러는 총 3개의 템플릿 클래스를 생성해야 한다. 그리고 이를 위해서는 클래스 템플릿인 Point의 모든 것을 알아야 한다.
즉, 컴파일러는 헤더파일에 담긴 정보뿐만 아니라, 소스파일에 담긴 정보를 참조해야만 한다. (소스파일에 정의되어있는 기능을 알아야 템플릿 클래스를 생성할 수 있기때문에)
그래서 일반적으로 파일을 나누면 참조할 만한 것이 없기 때문에 문제가 발생한다.
해결법
- 헤더파일에 템플릿의 모든 정보를 모두 넣는다.
- #include 문으로 소스파일도 포함시킨다. ex) #include "gg.cpp"
템플릿은 이러한 방법을 사용해서 템플릿의 모든 정보를 소스파일에 전달해야만 한다.
배열 클래스의 템플릿화
여기선 헤더파일 안에 클래스 템플릿 BoundCheckArray의 모든 것을 담아두었다. 따라서 이 헤더파일 하나만 포함을 하면, BoundCheckArray 템플릿 기반의 객체를 생성할 수 있다.
/* gg.h */
#ifndef __GG_H__
#define __GG_H__
#include <iostream>
#include <cstdlib>
using namespace std;
template <typename T>
class BoundCheckArray
{
private:
T * arr;
int arrLen;
BoundCheckArray(const BoundCheckArray& ref){ }
BoundCheckArray& operator=(const BoundCheckArray& ref){return *this;}
public:
BoundCheckArray(int len);
T& operator[](int idx);
T operator[](int idx) const;
int GetArrLen() const;
~BoundCheckArray();
};
template <class T>
BoundCheckArray<T>::BoundCheckArray(int len)
:arrLen(len)
{
arr = new T[len];
}
template <class T>
T& BoundCheckArray<T>::operator[](int idx)
{
if(idx < 0 || idx >= arrLen)
{
cout<<"Array index out of bound exception"<<endl;
exit(1);
}
return arr[idx];
}
template <class T>
T BoundCheckArray<T>::operator[](int idx) const
{
if(idx < 0 || idx >= arrLen)
{
cout<<"Array index out of bound exception"<<endl;
exit(1);
}
return arr[idx];
}
template <class T>
int BoundCheckArray<T>::GetArrLen() const
{
return arrLen;
}
template <class T>
BoundCheckArray<T>::~BoundCheckArray()
{
delete []arr;
}
#endif
/* point.h */
/* point.cpp */
/* main.cpp */