코드를 재활용하는 다음 방법으로는 템플릿을 이용하는 방법이 있다. 예전에 Stack 클래스를 만들어본 적이 있다. 그 클래스는 데이터형으로 unsinged long을 가졌다. 데이터형을 double이나 string으로 바꿀 수도 있었을 것이다. 물론 그때 데이터형 이외의 코드는 변하지 않을 것이다. 그러니 만약 다른 데이터형의 코드가 필요하다면, 클래스를 새로 작성하는 게 아니라, 임의의 데이터형이 감당 가능하도록 작성하는 게 코드를 재활용하는 방법이다. 다음은 이전에 작성한 Stack 클래스다.
typedef unsigned long Item;
class Stack
{
private:
enum {MAX = 10};
Item items[MAX];
int top;
public:
Stack();
bool IsEmpty() const;
bool IsFull() const;
bool Push(const Item& item);
bool Pop(Item& item);
};
이 Stack 정의를 템플릿 정의로, Stack 멤버 함수를 템플릿 멤버 함수로 바꾸겠다. 템플릿 함수처럼 다음과 같은 코드를 쓴다.
template <class Type>
or
template <typename Type>
함수처럼 저 구문 바로 밑에다가 클래스 정의를 하면 된다. 여기서 Type과 같은 포괄적인 데이터형 식별자를 '데이터형 매개 변수'라 한다. 일반적으로 Type이나, T 명칭을 많이 쓰고, 저 문구 대신에 데이터형이 들어간다. 꼭 자료형이 아니라 실제로 쓰일 포괄적인 데이터가 들어간다. ex) 기본 데이터형, 클래스, 구조체 등. 클래스 메서드 머리도 비슷하게 한다.
// 템플릿 전
bool Stack::Push(const Item & item)
{
...
}
// 템플릿 후
template <class Type> // or template <typename Type>
bool Stack<Type>::Push(const Type & item)
{
...
}
클래스 선언 안에서 정의된 메서드(인라인 함수)는 템플릿 제한자와 클래스 제한자를 생략 할 수 있다.
#pragma once
template <class Type>
class Stack
{
private:
enum {MAX = 10};
Type items[MAX];
int top;
public:
Stack();
bool IsEmpty() const;
bool IsFull() const;
bool Push(const Type& item);
bool Pop(Type& item);
};
template<class Type>
inline Stack<Type>::Stack()
{
top = 0;
}
template<class Type>
inline bool Stack<Type>::IsEmpty() const
{
return top == 0;
}
template<class Type>
inline bool Stack<Type>::IsFull() const
{
return top == MAX
}
template<class Type>
inline bool Stack<Type>::Push(const Type& item)
{
if (top < MAX)
{
items[top++] = item;
return true;
}
else
return false;
}
template<class Type>
inline bool Stack<Type>::Pop(Type& item)
{
if (top > 0)
{
item = items[--top];
return true;
}
else
return false;
}
이 템플릿들이 클래스와 멤버 함수 정의가 아님을 깨닫는 게 중요하다. 단지 클래스와 멤버 함수 정의를 생성하는 방법을 컴파일러에게 알려주는 지시문이다. 그래서 클래스 템플릿과 멤버 함수 템플릿이 한 파일에 쓰인다. 그리고 이걸 실행해서 type이 정해지면 구체화 or 특수화라고 부른다.
Stack<int> kernels; // int 값들의 스택 생성.
Stack<string> colonels; // string 객체들의 스택 생성.
이 두 선언을 컴파일러가 발견하면, Stack<Type> 템플릿을 사용하여 두 개의 서로 다른 클래스와, 클래스 메서드들의 집합을 생성할 것이다.
두 개 이상의 매개 변수도 사용할 수 있다.
template <class T1, class T2, ...>
또한 함수처럼 디폴트 값을 넣을 수도 있다.
template <class T1, class T2 = int>
class Topo...
Topo<double, double> m1; // M1, M2 둘 다 double형.
Topo<double> m2; // T1은 double형, T2는 int형.
너무 사사로운 것이 많아서 다음에 쓸 일 있을 때 해야겠다;