도순씨의 코딩일지
C++ :: 템플릿(Template), 클래스 템플릿(class Template) 본문
🌼 함수를 대상으로 템플릿 이해하기
함수 템플릿은 함수를 만들어내는 역할을 합니다. 함수의 기능은 결정되어 있지만, 자료형은 결정되어 있지 않습니다. 그러므로 자료형을 결정해주어야 합니다. 다시 한 번 말하자면 함수 템플릿은 함수를 만드는 도구입니다. 자바의 제네릭과 유사하죠. 예시를 통해서 함수 템플릿을 이해해봅시다.
1
2
3
|
int Add(int num1, int num2){
return num1 + num2;
}
|
cs |
위 함수의 정보를 요약해보면 다음과 같습니다.
💡 함수의 기능 : 덧셈
💡 대상 자료형 : int형 데이터
이러한 함수를 만들어낼 수 있는 템플릿은 다음과 같이 정의됩니다.
1
2
3
|
T Add(T num1, T num2){
return num1 + num2;
}
|
cs |
위 함수의 정보를 요약해봅시다.
💡 함수의 기능 : 덧셈
💡 대상 자료형 : 결정되어 있지 않음.
T는 자료형을 결정하지 않겠다는 의미로 사용한 것입니다. 그리고 다음과 같이 함수를 완성시킬 수 있습니다.
1
2
3
4
|
template <typename T>
T Add(T num1, T num2){
return num1 + num2;
}
|
cs |
위의 코드에서 첫 번째 줄은 T라는 의미를 이용하여 아래의 함수를 템플릿으로 정의한다는 의미입니다. 여기서 typename 대신 class를 사용하여도 상관 없습니다. 둘 다 빈번하게 사용되는 표현입니다.
그렇다면 두 가지 종류의 함수를 만들어봅시다.
💡 int형 덧셈을 진행하는 Add 함수
💡 double형 덧셈을 진행하는 Add 함수
⭐️AddFunctionTemplate.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
#include <iostream>
using namespace std;
template <typename T>
T Add(T num1, T num2){
return num1 + num2;
}
int main(void){
cout << Add<int> (15, 20) << endl;
cout << Add<double> (2.9, 3.7) << endl;
cout << Add<int> (3.2, 3.2) << endl;
cout << Add<double> (3.14, 2.75) << endl;
return 0;
}
|
cs |
⭐️AddFunctionTemplate.cpp 실행결과
1
2
3
4
|
35
6.6
6
5.89
|
cs |
그럼 함수를 템블릿으로 정의하면 매 호출순간마다 함수를 만들까요? 그렇지 않습니다. 한 번 함수가 만들어지면 그 다음에는 만들어진 함수를 호출할 뿐 새로 함수를 만들지 않습니다. 컴파일 속도의 감소가 발생하긴 하지만 실행 속도가 줄어드는 것은 아니기 때문에 크게 신경 쓸 요소는 아닙니다.
앞에서 보인 예제의 main 함수는 다음과 같이 변경해도 상관 없습니다.
1
2
3
4
5
6
7
|
int main(void){
cout << Add (15, 20) << endl;
cout << Add (2.9, 3.7) << endl;
cout << Add (3.2, 3.2) << endl;
cout << Add (3.14, 2.75) << endl;
return 0;
}
|
cs |
컴파일러가 인자의 자료형을 판단하고 적절한 실행결과를 도출하므로 위와 같이 코드를 작성해도 좋습니다.
이렇게 만들어지는 탬플릿 함수는 일반 함수와 구분이 된다. 두 종류의 함수는 공존할 수 있습니다. 아래의 예제를 살펴보도록 합시다.
⭐️ TwoTypeAddFunction.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
#include <iostream>
using namespace std;
template <typename T>
T Add(T num1, T num2){
cout << "T Add(T num1, T num2)" << endl;
return num1 + num2;
}
int Add(int num1, int num2){
cout << "Add(int num1, int num2)" << endl;
return num1 + num2;
}
double Add(double num1, double num2){
cout << "Add(double num1, double num2)" << endl;
}
int main(void){
cout << Add(5, 7) << endl;
cout << Add(3.7, 7.5) << endl;
cout << Add<int> (5, 7) << endl;
cout << Add<double> (3.7, 7.5) << endl;
return 0;
}
|
cs |
⭐️ TwoTypeAddFunction.cpp 실행결과
1
2
3
4
5
6
7
8
|
Add(int num1, int num2)
12
Add(double num1, double num2)
6.95329e-310
T Add(T num1, T num2)
12
T Add(T num1, T num2)
11.2
|
cs |
🌼 둘 이상의 형(Type)에 대해 템플릿 선언하기
템플릿의 정의에도 다양한 선언이 가능할 뿐만 아니라, 둘 이상의 형에 대해서 사용할 수 있습니다.
⭐️ PrimitiveFunctionTemplate.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
#include <iostream>
using namespace std;
template <class T1, class T2>
void ShowData(double num){
cout << T1(num) << ", " << (T2)num << endl;
}
int main(void){
ShowData<char, int> (65);
ShowData<char, int>(67);
ShowData<char, double>(68.9);
ShowData<short, double> (69.7);
ShowData<short, double> (70.4);
return 0;
}
|
cs |
⭐️ PrimitiveFunctionTemplate.cpp
1
2
3
4
5
|
A, 65
C, 67
D, 68.9
69, 69.7
70, 70.4
|
cs |
🌼함수 템플릿의 특수화(specialization)
⭐️ NeedSpecialFunctionTemplate.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
#include <iostream>
using namespace std;
template <typename T>
T Max(T a, T b){
return a > b ? a : b;
}
int main(void){
cout << Max(11, 15) << endl;
cout << Max('T', 'Q') << endl;
cout << Max(3.5, 7.5) << endl;
cout << Max("Simple", "Best") << endl;
return 0;
}
|
cs |
⭐️ NeedSpecialFunctionTemplate.cpp 실행결과
1
2
3
4
|
15
T
7.5
Best
|
cs |
하지만 위 코드에는 한계가 있습니다. 문자열 반환에 있어서 옳은 결과를 반환하지 못합니다. 만약 순서의 비교가 목적이라면 다음과 같이 작성해야 합니다.
1
2
3
|
const char* Max(const char* a, const char* b){
return strcmp(a, b) > 0 ? a : b;
}
|
cs |
이와 같이 템플릿의 함수 구성방법에 예외를 둘 필요가 있습니다. 이 때 사용하는 것이 '함수의 특수화'입니다. 다음 예제를 살펴봅시다.
⭐️ SpecialFunctionTemplate.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
#include <iostream>
#include <cstring>
using namespace std;
template <typename T>
T Max(T a, T b){
return a > b ? a : b;
}
template <>
char* Max(char* a, char* b){
cout << "char* Max<char*>(char* a, char* b)" << endl;
return strlen(a) > strlen(b) ? a : b;
};
template<>
const char* Max(const char* a, const char* b){
cout << "const char* Max<const char*>(const char* a, const char* b)" << endl;
return strcmp(a, b) > 0 ? a : b;
}
int main(void){
cout << Max(11, 15) << endl;
cout << Max('T', 'Q') << endl;
cout << Max(3.5, 7.5) << endl;
cout << Max("Simple", "Best") << endl;
char str1[] = "Simple";
char str2[] = "Best";
cout << Max(str1, str2) << endl;
return 0;
}
|
cs |
⭐️ SpecialFunctionTemplate.cpp 실행결과
1
2
3
4
5
6
7
|
15
T
7.5
const char* Max<const char*>(const char* a, const char* b)
Simple
char* Max<char*>(char* a, char* b)
Simple
|
cs |
11번째 라인과 17번째 라인에서 확인할 수 있듯 char* 형 함수와 const char*형 함수는 템플릿 함수가 필요한 경우에는 따로 제시를 해주고 있습니다.
🌼 클래스 템플릿
클래스 템플릿은 클래스를 템플릿으로 정의가 가능한 것을 뜻합니다. 예제를 통해서 알아봅시다.
⭐️ PointClassTemplate.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
#include <iostream>
using namespace std;
template <typename T>
class Point{
private:
T xpos, ypos;
public:
Point(T x = 0 , T y = 0) : xpos(x), ypos(y) {}
void ShowPosition() const{
cout << '[' << xpos << ", " << ypos << ']' << endl;
}
};
int main(void){
Point<int> pos1(3, 4);
pos1.ShowPosition();
Point<double> pos2(2.4, 3.6);
pos2.ShowPosition();
Point<char> pos3('P', 'F');
pos3.ShowPosition();
return 0;
}
|
cs |
⭐️ PointClassTemplate.cpp 실행결과
1
2
3
|
[3, 4]
[2.4, 3.6]
[P, F]
|
cs |
여기에서는 템플릿 함수를 호출할 때 <int>, <double>과 같은 자료형을 생략할 수 없습니다.
🌼 클래스 템플릿의 선언과 정의의 분리
클래스 템플릿도 멤버함수를 클래스 외부에서 정의하는 것이 가능합니다. 예제 코드를 한 번 살펴봅시다.
⭐️ PointClassTemplateFuncDef.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
#include <iostream>
using namespace std;
template <typename T>
class Point{
private:
T xpos, ypos;
public:
Point(T x = 0, T y = 0);
void ShowPosition() const;
};
template <typename T>
Point <T> :: Point (T x, T y) : xpos(x), ypos(y) {}
template <typename T>
void Point<T> :: ShowPosition() const {
cout << '[' << xpos << ", " << ypos << ']' << endl;
}
int main(void){
Point <int> pos1(3, 4);
pos1.ShowPosition();
Point <double> pos2(2.4, 3.6);
pos2.ShowPosition();
Point<char> pos3('P', 'F');
pos3.ShowPosition();
return 0;
}
|
cs |
⭐️ PointClassTemplateFuncDef.cpp 실행결과
1
2
3
|
[3, 4]
[2.4, 3.6]
[P, F]
|
cs |
📜 출처
윤성우(2010). 윤성우 열혈 C++ 프로그래밍. 오렌지미디어.
'𝐏𝐑𝐎𝐆𝐑𝐀𝐌𝐌𝐈𝐍𝐆 > 𝐂++' 카테고리의 다른 글
C++ :: 예외처리(try, catch, throw) (0) | 2020.09.02 |
---|---|
C++ :: 템플릿의 특수화, 인자, 매개변수, 디폴트값 (0) | 2020.09.01 |
C++ :: 디폴트 대입 연산자, 배열의 인덱스 연산자 오버로딩, const 함수 오버로딩 (0) | 2020.08.30 |
C++ :: 연산자 오버라이딩, 단항 연산자의 오버로딩, 전위증가와 후위증가 오버로딩 (0) | 2020.08.29 |
C++ :: 멤버함수와 가상함수의 동작원리 (0) | 2020.08.28 |