Data+

10. 클래스 템플릿의 이해1

by Qerogram

* 클래스 템플릿의 필요성을 우선 코드로 보자.

- 기획팀에서, 유저들이 게임에 접속하여 다른 유저들과 게임을 했을 때, 유저들의 경험치가 변경되는 이력을 보고싶다.

즉, 게임이 끝날 때 마다 경험치를 저장하여야 되고, 가장 최신에서 가장 오래된 순(LIFO)로 보여주어야 하니 Stack을 이용한다.

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
#include <iostream>
 
using namespace std;
 
const int MAX_EXP_COUNT = 100;
 
class ExpStack {
  public :
    ExpStack() {
      Clear();
    }
    
    void Clear() {
      m_Count = 0;
    }
    
    int Count() const {
      return m_Count;
    }
    
    bool IsEmpty() {
      return 0 == m_Count ? true : false;
    }
    
    bool push(float Exp) {
      if(m_Count > MAX_EXP_COUNT) return false;
      
      m_aData[m_Count] = Exp;
      ++m_Count;
      
      return true;
    }
    
    float pop() {
      if(m_Count < 1return 0.0f;
      --m_Count;
      return m_aData[m_Count];
    }
    
    private :
    float m_aData[MAX_EXP_COUNT];
    int m_Count;
    
};
 
int main() {
  ExpStack kExpStack;
  cout << "첫번째 게임 종료 - 경험치 145.5f" << endl;
  kExpStack.push(145.5f);
  cout << "두번째 게임 종료 - 경험치 183.25f" << endl;
  kExpStack.push(183.25f);
  cout << "세번째 게임 종료 - 경험치 162.3f" << endl;
  kExpStack.push(162.3f);
  
  int Count = kExpStack.Count();
  for(int i = 0 ; i < Count; ++i) cout <<"현재 경험치 -> " << kExpStack.pop() << endl;
  return 0;
}
cs


* 결과

첫번째 게임 종료 - 경험치 145.5f
두번째 게임 종료 - 경험치 183.25f
세번째 게임 종료 - 경험치 162.3f
현재 경험치 -> 162.3
현재 경험치 -> 183.25
현재 경험치 -> 145.5


- 이번에는, 돈 변경 이력을 보고싶다고 하여, 또 아래와 같이 만들었다.

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>
 
using namespace std;
 
const int MAX_MONEY_COUNT = 100;
 
class MoneyStack {
  public :
    MoneyStack() { Clear() }
    void Clear() { m_Count = 0; }
    int Count() const { return m_Count; }
    bool push(int Money) {
      if(m_Count >= MAX_MONEY_COUNT ) return false;
      m_aData[m_Count] = Money;
      ++m_Count;
      return true;
    }
    int pop() {
      if(m_Count < 1return 0;
      --m_Count;
      return m_aData[m_Count] ;
    }
    private:
    int m_aData[MAX_MONEY_COUNT];
    int m_Count;
};
cs


- 얼추 이런 식의 코드가 나오게 되는데, ExpStack Class와 몹시 유사하다. 이러한 경우 Template을 이용하자.



* Class Template 문법

template <typename type> class 클래스 이름

ex) template <typename T> class Stack { ... };


* Stack Class를 Class Template으로 정의를 해본다면,

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
#include <iostream>
 
using namespace std;
 
const int MAX_COUNT = 100;
 
template <typename T> 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; }
    bool push(T data) {
      if(m_Count >= MAX_COUNT) return false;
      m_aData[m_Count++= data;
      return true;
    }
    T pop() {
      if(m_Count < 1return 0;
      m_Count--;
      return m_aData[m_Count];
    }
    private :
      T m_aData[MAX_COUNT];
      int m_Count;
};
 
 
int main() {
  Stack<double> kStackExp;
  cout << "첫번째 게임 종료 - 현재 경험치 145.5f" << endl;
  kStackExp.push(145.5f);
  cout <<"두번재 게임 종료 - 현재 경험치 183.25f" << endl;
  kStackExp.push(183.25f);
  cout <<"세번째 게임 종료 - 현재 경험치 162.3f" << endl;
  kStackExp.push(162.3f);
  
  int Count = kStackExp.Count();
  for(int i =0; i < Count; ++i) {
    cout << "현재 경험치 ->" << kStackExp.pop() << endl;
  }
  
  cout << endl << endl;
  
  Stack<int> kStackMoney;
  
  cout << "첫번째 게임 종료 - 현재 돈 1000023" << endl;
  kStackMoney.push(1000023);
  cout << "두번째 게임 종료 - 현재 돈 1000234" << endl;
  kStackMoney.push(1000234);
  cout << "세번째 게임 종료 - 현재 돈 1000145" << endl;
  kStackMoney.push(1000145);
  
  Count = kStackMoney.Count();
  for(int i = 0; i < Count; ++i) {
    cout << "현재 돈 -> " << kStackMoney.pop() << endl;
  }
  return 0;
}
cs

*결과

첫번째 게임 종료 - 현재 경험치 145.5f
두번재 게임 종료 - 현재 경험치 183.25f
세번째 게임 종료 - 현재 경험치 162.3f
현재 경험치 ->162.3
현재 경험치 ->183.25
현재 경험치 ->145.5


첫번째 게임 종료 - 현재 돈 1000023
두번째 게임 종료 - 현재 돈 1000234
세번째 게임 종료 - 현재 돈 1000145
현재 돈 -> 1000145
현재 돈 -> 1000234
현재 돈 -> 1000023


* Class Template에서 Non-type Parameter 사용.

- 바로 앞에서 Stack Class를 정의했을 땐, 저장할 수 있는 공간이 100개로 한정되어 있는데, 공간의 크기가 변경될 수 있어야 사용하기에 적합하다. 고로, Function Template때 하였던 None-Type으로 하면 해결이 된다.

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
#include <iostream>
 
using namespace std;
 
template <typename T, int Size>
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 < 1return 0;
      --m_Count;
      return m_aData[m_Count];
    }
    
    private :
      T m_aData[Size];
      int m_Count;
};
 
int main() {
  Stack<int100> kStack1;
  cout << "스택의 크기는 ? " << kStack1.GetStackSize() << endl;
  Stack<double60> kStack2;
  cout << "스택의 크기는 ? " << kStack2.GetStackSize() << endl;
  return 0;
}
cs


* 결과

스택의 크기는 ? 100
스택의 크기는 ? 60


* 참고 - Thinking about C++ STL Programming

'코딩 > C&C++' 카테고리의 다른 글

12. 클래스 템플릿의 이해3  (0) 2017.04.15
11. 클래스 템플릿의 이해2  (0) 2017.04.15
9. 함수 템플릿의 이해2  (0) 2017.04.13
8. 함수 템플릿의 이해1  (0) 2017.04.13
7. Merge sort(합병정렬)  (0) 2017.04.10

블로그의 정보

Data+

Qerogram

활동하기