14. 템플릿
1. 템플릿
템플릿은 함수나 클래스와 같은 객체를 생성할 때, 이러한 함수나 클래스를 찍어내는 주형 또는 틀과 같은 역할을 한다.
예를 들어, int
타입 데이터를 저장할 수 있는 동적 배열을 구현한다고 가정하자. 이후에 float
타입 데이터를 저장할 동적 배열이 필요해 진다면, 이전에 int
동적 배열의 코드를 일부만 수정해서 하나의 클래스를 다시 정의해야 한다.
이러한 비효율적인 과정을 줄이기 위해, C++ 에서 객체가 선언될 때 자료형을 지정하여 입력받고 자료형을 객체 정의 내부에 넣어 선언과 동시에 틀에서 찍어내듯이 해당 함수 또는 클래스를 정의해 주는 것이 바로 템플릿이다.
template <typename T>
class Vector{
T* data;
int capacity;
int count;
}
...
//객체 선언
Vector<float> fvec;
위의 코드에서, 클래스 Vector는 템플릿 인자로 T를 받으며, T는 반드시 어떠한 자료형을 받아야 한다.
이후 해당 자료형의 객체를 선언할 때, <> 를 클래스(또는 함수)의 이름 뒤에 붙여 자료형을 지정하면, 이 때 해당 자료형이 T에 들어가는 클래스(또는 함수)가 정의된다.
그 이전에는 정의되지 않으므로, 만약 해당 클래스를 파일 분할하여 구현할 경우, 템플릿은 반드시 헤더 파일에 구현해야 한다.
헤더가 아닌 cpp 파일에 구현될 경우, 헤더만을 include 하는 다른 파일에서는 객체 선언 시 해당 함수 또는 클래스의 존재만 정의되고 내부 구현은 정의되지 않으므로, 이후에 링크 과정에서 오류가 발생한다.
2. 함수 템플릿
#pragma once
template<typename T>
T Add(T _a, T _b) {
return _a + _b;
}
함수 템플릿은 위와 같이 구현이 가능하다. 위의 예시는 입력받은 두 변수를 함수 호출 시 변수 타입을 지정하여 호출한 후, 해당 자료형에 해당하는 합연산을 수행하는 함수이다.
이를 함수 오버로딩으로 해결하려 하면 같은 함수가 자료형의 개수만큼 필요하므로 템플릿으로 효율적인 구현이 가능하다.
3. 클래스 템플릿
#pragma once
template<typename T>
class Node {
private:
T data;
Node* prevNode;
Node* nextNode;
};
template<typename T>
class List {
private:
Node<T>* headNode;
int count;
public:
//...
};
위의 예시는 T 라는 자료형을 저장하는 노드와, 그 노드로 이루어진 리스트 구현의 일부이다.
이처럼 클래스의 구현에도 템플릿으로 자료형을 유동적으로 받아 올 수 있다.
이후 이 리스트를 호출 할 경우 아래와 같이 호출할 수 있다.
#include "cpp14.h"
int main() {
List<int> iList; // int 데이터를 저장하는 리스트 객체 선언
return 0;
}