
함수 템플릿
어떤 함수를 중복 함수로 구현할 때 매개변수의 자료형이 int
, double
형으로만 구분된다면, 동일한 코드 작성이 불가능하다. int
, double
형으로만 예를 들었지만, 다양한 경우 함수 동작이 자료형과 관계없이 동작하는데 자료형 때문에 중복 함수로 구현이 불가능한 경우가 있다. 이때 템플릿을 사용하여 자료형을 일반화시켜 함수를 구현할 수 있다.
예를 들어 아래와 같은 두 함수가 있다고 가정하자.
void print(int a) {
cout << a;
}
void print(double a) {
cout << a;
}
간단한 코드이지만 매개변수로 받을 때 int
인지 double
인지 구분 불가능하기 때문에 중복해서 사용할 수 없는 함수들이다.
이때 template
키워드를 이용하여 자료형을 일반화시켜 아래와 같이 함수를 일반화시킬 수 있다. 이를 제네릭 함수라고 한다.
template <typename T>
void print(T a) {
cout << a;
}
이때 template <typename T>
를 템플릿 선언이라 하고, typename
대신 class
를 사용할 수도 있다. T 는 제네릭 타입이다.
컴파일이 진행되면 함수가 실제 사용된 부분에 대해서 구체화(specialization)을 진행하여 제네릭 타입을 실제 자료형으로 변환하여 함수를 만들고 해당 함수를 호출한다.
이러한 템플릿 함수는 소프트웨어 생산성 측면에서 장점이 있지만, 컴파일러에 따라 지원하지 않을 수 있다는 단점도 있을 뿐더러 컴파일 시에 매개변수의 자료형에 따라 인스턴스화(instantiation)되므로, 예상치 못한 자료형이 전달될 경우 컴파일 오류나 디버깅이 까다로운 에러가 발생할 수 있다는 단점이 있다.
더하여 템플릿 함수보다 중복 함수가 우선이다. 예를 들어 아래와 같은 코드가 있다고 가정하자.
#include <iostream>
using namespace std;
template <typename T>
void print(T a) {
cout << a << endl;
}
void print(char a) {
cout << (int)a << endl;
}
int main() {
print(10);
print('a');
}
출력은 다음과 같다.
10
97
a 가 아니라 97이 출력된 것은 char
형 매개변수를 받는 print 함수가 중복 함수라서 템플릿 함수보다 우선순위가 높기 때문에 print('a'); 가 char
형 매개변수를 받은 print 함수를 호출하여 'a' 를 int
형으로 변환하여 출력하였기 때문이다.
클래스 템플릿
템플릿을 사용하여 자료형을 일반화할 수 있다.
예를 들어 아래와 같은 클래스를 가정하자. 참고로 스택이 비어있을 때 NULL
을 반환한 것은 임의로 지정한 것이다.
class Stack {
int data[100];
int top;
public:
Stack() {
top = -1;
}
void push(int item) {
if (top >= 99) return;
data[++top] = item;
}
int pop() {
if (top < 0) return NULL;
return data[top--];
}
};
이러한 스택 클래스에는 int
형 변수만 집어넣을 수 있는데, 다른 자료형도 넣고 싶다면 아래와 같이 템플릿을 이용하여 일반화시켜 사용할 수 있다.
template <typename T>
class Stack {
T data[100];
int top;
public:
Stack() {
top = -1;
}
void push(T item) {
if (top >= 99) return;
data[++top] = item;
}
T pop() {
if (top < 0) return NULL;
return data[top--];
}
};
이렇게하면 int
형 변수 뿐 아니라 다양한 자료형을 스택에 담을 수 있다. 참고로 클래스에서 선언만 하고 따로 구현해줄 경우 아래와 같이 구현해주면 된다.
template <typename T> void Stack<T>::push(T item) {
if (top >= 99) return;
data[++top] = item;
}
즉 반드시 템플릿을 앞에 선언해야 하고 클래스 이름 뒤에 <>
을 통해 제네릭 타입을 명시해주어야 한다.
이 클래스의 객체 생성은 아래와 같이 하면 된다. 이 경우 데이터에 string
타입이 들어간다.
Stack<string> stack;
혹은 다음과 같이 동적 할당 할 수 있다. 이 경우 데이터에 int
타입이 들어간다.
Stack<int>* stack = new Stack<int>();
'Language > C & C++' 카테고리의 다른 글
[C++] auto 키워드 (0) | 2024.11.14 |
---|---|
[C++] 표준 템플릿 라이브러리(STL) (0) | 2024.11.14 |
[C++] virtual 키워드를 활용한 함수 오버라이딩 및 추상 클래스 (0) | 2024.11.13 |
[C++] 업캐스팅(upcasting) 및 다운캐스팅(downcasting) (0) | 2024.11.13 |
[C++] 클래스 상속(inheritance) 및 다중 상속 (0) | 2024.11.01 |

함수 템플릿
어떤 함수를 중복 함수로 구현할 때 매개변수의 자료형이 int
, double
형으로만 구분된다면, 동일한 코드 작성이 불가능하다. int
, double
형으로만 예를 들었지만, 다양한 경우 함수 동작이 자료형과 관계없이 동작하는데 자료형 때문에 중복 함수로 구현이 불가능한 경우가 있다. 이때 템플릿을 사용하여 자료형을 일반화시켜 함수를 구현할 수 있다.
예를 들어 아래와 같은 두 함수가 있다고 가정하자.
void print(int a) {
cout << a;
}
void print(double a) {
cout << a;
}
간단한 코드이지만 매개변수로 받을 때 int
인지 double
인지 구분 불가능하기 때문에 중복해서 사용할 수 없는 함수들이다.
이때 template
키워드를 이용하여 자료형을 일반화시켜 아래와 같이 함수를 일반화시킬 수 있다. 이를 제네릭 함수라고 한다.
template <typename T>
void print(T a) {
cout << a;
}
이때 template <typename T>
를 템플릿 선언이라 하고, typename
대신 class
를 사용할 수도 있다. T 는 제네릭 타입이다.
컴파일이 진행되면 함수가 실제 사용된 부분에 대해서 구체화(specialization)을 진행하여 제네릭 타입을 실제 자료형으로 변환하여 함수를 만들고 해당 함수를 호출한다.
이러한 템플릿 함수는 소프트웨어 생산성 측면에서 장점이 있지만, 컴파일러에 따라 지원하지 않을 수 있다는 단점도 있을 뿐더러 컴파일 시에 매개변수의 자료형에 따라 인스턴스화(instantiation)되므로, 예상치 못한 자료형이 전달될 경우 컴파일 오류나 디버깅이 까다로운 에러가 발생할 수 있다는 단점이 있다.
더하여 템플릿 함수보다 중복 함수가 우선이다. 예를 들어 아래와 같은 코드가 있다고 가정하자.
#include <iostream>
using namespace std;
template <typename T>
void print(T a) {
cout << a << endl;
}
void print(char a) {
cout << (int)a << endl;
}
int main() {
print(10);
print('a');
}
출력은 다음과 같다.
10
97
a 가 아니라 97이 출력된 것은 char
형 매개변수를 받는 print 함수가 중복 함수라서 템플릿 함수보다 우선순위가 높기 때문에 print('a'); 가 char
형 매개변수를 받은 print 함수를 호출하여 'a' 를 int
형으로 변환하여 출력하였기 때문이다.
클래스 템플릿
템플릿을 사용하여 자료형을 일반화할 수 있다.
예를 들어 아래와 같은 클래스를 가정하자. 참고로 스택이 비어있을 때 NULL
을 반환한 것은 임의로 지정한 것이다.
class Stack {
int data[100];
int top;
public:
Stack() {
top = -1;
}
void push(int item) {
if (top >= 99) return;
data[++top] = item;
}
int pop() {
if (top < 0) return NULL;
return data[top--];
}
};
이러한 스택 클래스에는 int
형 변수만 집어넣을 수 있는데, 다른 자료형도 넣고 싶다면 아래와 같이 템플릿을 이용하여 일반화시켜 사용할 수 있다.
template <typename T>
class Stack {
T data[100];
int top;
public:
Stack() {
top = -1;
}
void push(T item) {
if (top >= 99) return;
data[++top] = item;
}
T pop() {
if (top < 0) return NULL;
return data[top--];
}
};
이렇게하면 int
형 변수 뿐 아니라 다양한 자료형을 스택에 담을 수 있다. 참고로 클래스에서 선언만 하고 따로 구현해줄 경우 아래와 같이 구현해주면 된다.
template <typename T> void Stack<T>::push(T item) {
if (top >= 99) return;
data[++top] = item;
}
즉 반드시 템플릿을 앞에 선언해야 하고 클래스 이름 뒤에 <>
을 통해 제네릭 타입을 명시해주어야 한다.
이 클래스의 객체 생성은 아래와 같이 하면 된다. 이 경우 데이터에 string
타입이 들어간다.
Stack<string> stack;
혹은 다음과 같이 동적 할당 할 수 있다. 이 경우 데이터에 int
타입이 들어간다.
Stack<int>* stack = new Stack<int>();
'Language > C & C++' 카테고리의 다른 글
[C++] auto 키워드 (0) | 2024.11.14 |
---|---|
[C++] 표준 템플릿 라이브러리(STL) (0) | 2024.11.14 |
[C++] virtual 키워드를 활용한 함수 오버라이딩 및 추상 클래스 (0) | 2024.11.13 |
[C++] 업캐스팅(upcasting) 및 다운캐스팅(downcasting) (0) | 2024.11.13 |
[C++] 클래스 상속(inheritance) 및 다중 상속 (0) | 2024.11.01 |