Chap 13. 템플릿(Template) 1
13-1. 템플릿에 대한 이해와 함수
1 2 | int add(int, int); double add(double, double); | cs |
템플릿은 말 그대로, 틀을 의미한다. 우리가 더하기를 수행하는 함수를 만들 때, 자료형이 다른 경우 오버로딩으로 해결하려하여도 반환형 까지 다르면 완전히 다른 함수를 만들어야 한다. 이 때, 우리는 자료형에 독립적인 함수를 만들 수 있는데 (정확히는 함수의 틀을 만들 수 있다) 그것이 바로 템플릿이다.
1 2 3 4 | template <typename T> T add(T num1, T num2){ return num1+num2; } | cs |
다음과 같이, template을 선언해주고 자료형 매개변수로 T가 어떤 의미인지 명시해준다. 그리고 원하는 자료형 부분을 T로 치환해주면 우리가 원하는 함수 템플릿을 만들어줄 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #include <iostream> using namespace std; template <typename T> T add(T num1, T num2){ return num1+num2; } void main(){ cout<<add<int>(3,4)<<endl; cout<<add<double>(2.4, 5.7)<endl; cout<<add(2,5)<<endl; cout<<add('a','b')<<endl; } | cs |
실 사용은 다음과 같이 이루어지는데 이 때, 컴파일러가 컴파일 때 미리 보고 우리가 원하는 형의 자료형 만큼 함수를 만들어 둔다. 그리고 12~13 라인 처럼 자료형을 명시해주지않아도 컴파일러가 판단이 가능할 경우에는 다음과 같이 사용이 가능하다(그러나 되지 않을 때도 있으니 주의하고 사용하도록 하여야 한다).
이러한 템플릿으로 함수 틀을 만들어 둔 것을 보고 함수 템플릿이라 하고 컴파일러가 이를 보고 만드는 함수를 템플릿 함수라고 한다. 또한 특별한 자료형의 경우에 대해서는 우리가 미리 선언해 둘 수 있는데 이를 함수 템플릿의 특수화라고 한다.
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 | #include <iostream> #include <cstring> using namespace std; template <typename T> T add(T num1, T num2){ return num1+num2; } template <> const char* add<const char *>(const char* str1, const char* str2){ char tempstr[100]; strcpy(tempstr,str1); strcat(tempstr,str2); return tempstr; } void main(){ cout<<add<int>(3,4)<<endl; cout<<add<double>(2.4, 5.7)<endl; cout<<add(2,5)<<endl; cout<<add('a','b')<<endl; cout<<add<const char*>("asd", "bsd")<<endl; } | cs |
13-2. 클래스 템플릿
함수와 마찬가지로 클래스에 대해서도 템플릿을 선언하여 사용할 수 있다.
함수 템플릿과 마찬가지로 사용방법은 동일하지만 클래스 템플릿은 함수 템플릿과 달리 객체 생성자를 호출 시에 반드시 명시를 해주어야 한다. 왜냐하면 생성자와 별개로 자료형이 다를 수 있기에 컴파일러가 쉽게 판단할 수 없기 때문이다. 그래서 우리가 자료형을 명시해주어야 한다.
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 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | #include <iostream> using namespace std; template <typename T> class BoundCheckArray{ private: T * arr; int len; public: // 생성자 BoundCheckArray(int l) :len(l){ arr = new T[len]; } // 복사 생성자 BoundCheckArray(const BoundCheckArray & arr){} // = 연산자 BoundCheckArray& operator=(const BoundCheckArray & arr){} // [] 연산자 T& operator[](int idx){ if (idx <0 || idx >= len) exit(1); return arr[idx]; } // [] 연산자 const 오버로딩 T operator[](int idx) const{ if (idx <0 || idx >= len) exit(1); return arr[idx]; } // 소멸자 ~BoundCheckArray(){ delete[] arr; } }; // 메인 함수 void main(){ BoundCheckArray<int> intArr(5); BoundCheckArray<double> doubleArr(2); intArr[4] = 3; doubleArr[1] = 2.5; cout<<intArr[4]<<endl; cout<<doubleArr[1]<<endl; } | cs |
추가로, 템플릿은 헤더파일과 소스파일을 나눠놨을 때, 헤더파일만 메인 소스파일에 include 할 경우 에러가 난다. 컴파일러가 main 함수를 보고 컴파일 할시에 정의 부가 있어야 컴파일러가 함수든 클래스든 그에 맞게 만들어 둘 수 있기에 정의 부분이 있어야한다. 따라서 헤더파일에 정의 부분을 포함시키거나, 소스파일(cpp)도 메인 소스파일에 include 해주어야 한다.
'Archived(CSE Programming) > cpp' 카테고리의 다른 글
Chap 15. 예외처리(Exception Handling) (0) | 2019.01.16 |
---|---|
Chap 14. 템플릿(Template) 2 (0) | 2019.01.15 |
Chap 12. String 클래스의 디자인 (0) | 2019.01.13 |
Chap 11. 연산자 오버로딩 2 (0) | 2019.01.13 |
Chap 10. 연산자의 오버로딩 1 (0) | 2019.01.12 |