11. 클래스 템플릿의 이해2
by Qerogram* 템플릿 Param 디폴트 값 사용.
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 | template <typename T, int Size=100> class Stack { public: Stack() { Clear(); } void Clear() { m_Count = 0; } int Count() const { return m_Count; } bool IsEmpty() const { return 0 == m_Count ? true : false; } int GetStackSize() const { return Size; } bool push( T data ) { if( m_Count >= Size ) return false; m_aData[ m_Count++ ] = data; return true; } T pop() { if( m_Count < 1 ) return 0; --m_Count; return m_aData[ m_Count ]; } private: T m_aData[Size]; int m_Count; }; #include <iostream> using namespace std; int main() { Stack<int, 64> kStack1; cout << "kStack1의 크기는 " << kStack1.GetStackSize() << endl; Stack<double> kStack2; cout << "kStack2의 크기는" << kStack2.GetStackSize() << endl; return 0; } | cs |
* 결과
kStack1의 크기는 64
kStack2의 크기는100
* 생성자를 이용한 스택크기 설정.
- 생성자에 explicit 키워드를 붙이면 암시적인 형 변환이 불가능하다.
-> 만약 Stack kStack1 = 64;로 선언을 해버리면 컴파일 에러가 발생한다.
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 | template <typename T, int Size=100> class Stack { public: explicit Stack(int size) { m_Size = size; m_aData = new T[m_Size]; Clear(); } ~Stack() { delete[] m_aData; } void Clear() { m_Count = 0; } int Count() const { return m_Count; } bool IsEmpty() const { return 0 == m_Count ? true : false; } int GetStackSize() const { return m_Size; } bool push( T data ) { if( m_Count >= Size ) return false; m_aData[ m_Count++ ] = data; return true; } T pop() { if( m_Count < 1 ) return 0; --m_Count; return m_aData[ m_Count ]; } private: T* m_aData; int m_Count; int m_Size; }; #include <iostream> using namespace std; int main() { Stack<int> kStack1(64); cout << "kStack1의 크기는 " << kStack1.GetStackSize() << endl; return 0; } | cs |
* 결과
kStack1의 크기는 64
* 클래스 템플릿 전문화
- 같이 게임을 했던 유저의 아이디를 저장해서 보여주고 싶은데, 기존 스택 클래스는 기본 자료형을 사용하는 걸 전제로했는데 문자열이라 표기가 안된다. 이런경우 전문화를 사용한다.
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 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | #include <string.h> #include <iostream> const int MAX_ID_LENGTH = 21; void strncpy_s(char *dest,size_t size, const char *source, size_t n) { size_t i; for(i = 0; i < n; i++) *(dest+i) = *(source+i); } template<typename T> class Stack { public : explicit Stack(int size) { m_Size = size; m_aData = new T[m_Size]; Clear(); } ~Stack() { delete[] m_aData; } void Clear() { m_Count = 0; } int Count() const { return m_Count; } bool IsEmpty() const { return 0 == m_Count ? true : false; } int GetStackSize() const { return m_Size; } bool push(T data) { if(m_Count >= m_Size) return false; m_aData[m_Count++] = data; return true; } T pop() { if(m_Count < 1) return 0; --m_Count; return m_aData[m_Count]; } private : T* m_aData; int m_Count; int m_Size; }; template<> class Stack<char*> { public : explicit Stack(int size) { m_Size = size; m_ppData = new char*[m_Size]; for(int i = 0; i < m_Size; ++i) m_ppData[i] = new char[MAX_ID_LENGTH]; Clear(); } ~Stack() { for(int i =0; i < m_Size; ++i) delete[] m_ppData[i]; delete[] m_ppData; } void Clear() { m_Count = 0; } int Count() const { return m_Count; } bool IsEmpty() const { return 0 == m_Count ? true : false; } int GetStackSize() const { return m_Size; } bool push(char* pID) { if(m_Count >= m_Size) return false; strncpy_s(m_ppData[m_Count], MAX_ID_LENGTH, pID, MAX_ID_LENGTH - 1); m_ppData[m_Count][MAX_ID_LENGTH-1] = '\0'; ++m_Count; return true; } char* pop() { if(m_Count < 1) return 0; --m_Count; return m_ppData[m_Count]; } private : char** m_ppData; int m_Count; int m_Size; }; using namespace std; int main() { Stack<int> kStack1(64); cout << "스택의 크기는 : " <<kStack1.GetStackSize() << endl; kStack1.push(10); kStack1.push(11); kStack1.push(12); int Count1 = kStack1.Count(); for(int i = 0; i< Count1; ++i) cout << "유저 레벨 변화 => " << kStack1.pop() << endl; cout << endl; char GameID1[MAX_ID_LENGTH] ="NiceChoi"; char GameID2[MAX_ID_LENGTH] = "SuperMan"; char GameID3[MAX_ID_LENGTH] = "Attom"; Stack<char*> kStack2(64); kStack2.push(GameID1); kStack2.push(GameID2); kStack2.push(GameID3); int Count2 = kStack2.Count(); for(int i = 0; i < Count2; ++i) cout << "같이 게임을 한 유저의 ID =>" << kStack2.pop() << endl; return 0; } | cs |
* 결과
스택의 크기는 : 64
유저 레벨 변화 => 12
유저 레벨 변화 => 11
유저 레벨 변화 => 10
같이 게임을 한 유저의 ID =>Attom
같이 게임을 한 유저의 ID =>SuperMan
같이 게임을 한 유저의 ID =>NiceChoi
* 클래스 템플릿 부분 전문화
- 클래스 템플릿은 일부를 포인터나, 참조 혹은 구체적인 type 사용으로 부분 전문화가 가능하다.
* 구체적 type 사용에 의한 부분 전문화 문법 (아래의 코드를 보면 정확하다)
- template<typename T1, typename T2> class Test {...};
=> template <typename T1> class Test {...};
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 | #include <iostream> using namespace std; template <typename T1, typename T2> class Test{ public : T1 Add(T1 a, T2 b) { cout << "일반 템플릿을 사용!" << endl; return a; } }; template <typename T1> class Test<T1, float>{ public : T1 Add(T1 a, float b) { cout << "부분 전문화 템플릿 사용!" << endl; return a; } }; int main() { Test<int, int> test1; test1.Add(2, 3); Test<int, float> test2; test2.Add(2, 3.0f); return 0; } | cs |
* 결과
일반 템플릿을 사용!
부분 전문화 템플릿 사용!
* 참고 - Thinking About C++ STL Programming
'코딩 > C&C++' 카테고리의 다른 글
13. STL list1 (0) | 2017.04.15 |
---|---|
12. 클래스 템플릿의 이해3 (0) | 2017.04.15 |
10. 클래스 템플릿의 이해1 (0) | 2017.04.14 |
9. 함수 템플릿의 이해2 (0) | 2017.04.13 |
8. 함수 템플릿의 이해1 (0) | 2017.04.13 |
블로그의 정보
Data+
Qerogram