------

[ AD ] Port Monitor ( Try to use a Best WebSite Monitoring Tool )

------

http://goo.gl/fOmL

C9 Lectures: Stephan T. Lavavej - Standard Template Library (STL), 1 of n



Welcome to another installment of C9 Lectures. In the following series, learn all about STL from the great Stephan T. Lavavej, Microsoft's keeper of the STL cloth (this means he manages the partnership with the owners of STL and Microsoft, including, of course, bug fixes and enhancements to the STL that ships as part of Visual C++).

In this first part, Stephan introduces STL and then demonstrates many of its core features
(iterators, algorithms, and data structures).

As is Stephan's nature, he elaborates on technical details in very substantive way.
The Standard Template Library, or
STL, is a C++ library of container classes, algorithms, and iterators.
STL provides many fundamental algorithms and data structures.

The STL is a general purpose library:
 its components are heavily parameterized such that almost every component in the STL is a
template.



This is not an introductory series on C++.

As such, it is expected that viewers already possess a working knowledge of the C++ language.

Go ahead and open VC++ IDE and follow along--there are many examples provided on-screen and Stephan will monitor this thread and answer questions.


Enjoy. Learn.

Books mentioned by Stephen:

The C++ Standard Library: A Tutorial And Reference by Nicolai M. Josuttis

Effective STL by Scott Meyers   :

http://goo.gl/0FbW



Right click “Save as…”

'온라인게임 > stl' 카테고리의 다른 글

클래스 템플릿 2-2  (0) 2010.10.01
함수 템플릿 Template 2-1  (0) 2010.10.01
STL이 무엇인지 알고 계십니까? 1  (0) 2010.10.01

제공: 한빛 네트워크
저자: 최흥배
이전기사: 이전 기사에서는 함수 템플릿에 대해 설명을 했으니 이번에는 클래스 템플릿에 대해서 설명하려고 합니다.

 

경험치 변경 이력 저장

기획팀에서 유저들이 게임에 접속하여 다른 유저들과 100번의 게임을 했을 때 유저들의 경험치가 변경 되는 이력을 볼 수 있기를 요청 하였습니다.

기획팀의 요구를 들어주기 위해서 저는 게임이 끝날 때마다 경험치를 저장합니다.
또 경험치 이력 내역을 출력할 때 가장 최신에서 가장 오랜 된 것을 보여줘야 되기 때문에 스택(stack)이라는 자료 구조를 사용합니다.
스택은 자료 구조 중의 하나로 가장 마지막에 들어 온 것을 가장 먼저 꺼내는 LIFO(Last In First Out) 형식으로 되어 있습니다. 데이터를 넣을 때를 push, 빼낼 때는 pop이라는 이름을 일반적으로 사용한다.
경험치 이력을 저장하는 클래스의 구현과 이것을 사용하는 것은 아래와 같습니다.

// 경험치를 저장할 수 있는 최대 개수
const int MAX_EXP_COUNT = 100;

// 경험치 저장 스택 클래스
class ExpStack
{
public:
  ExpStack()
  {
    Clear();
  }

  // 초기화 한다.
  void Clear()
  {
    m_Count = 0;
  }

  // 스택에 저장된 개수
  int Count()
  {
    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()
  {
    // 저장된 것이 없다면 0.0f를 반환한다.
    if( m_Count  < 1 )
    {
      return 0.0f;
    }

    // 개수를 하나 감소 후 반환한다.
    --m_Count;
    return m_aData[ m_Count ];
  }

private:
  float  m_aData[MAX_EXP_COUNT];
  int    m_Count;
};

#include 

using namespace std;

void 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;
  }
}
실행 결과

그림1

실행 결과를 보면 알 수 있듯이 스택 자료구조를 사용하였기 때문에 제일 뒤에 넣은 데이터가 가장 제일 먼저 출력 되었습니다.

게임 돈 변경 이력도 저장해 주세요

경험치 변경 이력을 저장하고 출력하는 기능을 만들어서 기획팀에 보여주니 이번에는 게임 돈의변경 이력도 보고 싶다고 말합니다.

위에서 경험치 변경 이력 저장 기능을 만들어 보았으니 금방 할 수 있는 것이죠. 그래서 이번에는 이전 보다 훨씬 더 빨리 만들었습니다.

// 돈을 저장할 수 있는 최대 개수
const int MAX_MONEY_COUNT = 100;

// 돈 저장 스택 클래스
class MoneyStack
{
public:
  MoneyStack()
  {
    Clear();
  }

  // 초기화 한다.
  void Clear()
  {
    m_Count = 0;
  }

  // 스택에 저장된 개수
  int Count()
  {
    return m_Count;
  }

  // 저장된 데이터가없는가?
  bool IsEmpty()
  {
    return 0 == m_Count ? true : false;
  }

  // 돈을 저장한다.
  bool push( __int64 Money )
  {
    // 저장 할 수 있는 개수를 넘는지 조사한다.
    if( m_Count >= MAX_MONEY_COUNT )
    {
      return false;
    }

    // 저장후 개수를 하나 늘린다.
    m_aData[ m_Count ] = Money;
    ++m_Count;

    return true; 
  }

  // 스택에서 돈을 빼낸다.
  __int64 pop()
  {
    // 저장된 것이 없다면 0을 반환한다.
    if( m_Count  < 1 )
    {
      return 0;
    }

    // 개수를 하나 감소 후 반환한다.
    --m_Count;
    return m_aData[ m_Count ];
  }

private:
  __int64  m_aData[MAX_MONEY_COUNT];
  int  m_Count;
};

 

ExpStack 클래스와 MoneyStack 클래스가 비슷합니다

게임 돈 변경 이력 저장 기능을 가지고 있는 MoneyStack 클래스를 만들고 보니 앞에 만든 ExpStack와 거의 같습니다.
저장하는 데이터의 자료형만 다를뿐이지 모든 것이 같습니다.

그리고 기획팀에서는 게임 캐릭터의 Level 변경 이력도 저장하여 보여주기를 바라는 것 같습니다.
이미 거의 똑같은 클래스를 두개 만들었고 앞으로도 기획팀에서 요청이 있으면 더 만들 것 같습니다.

이렇게 자료형만 다른 클래스를 어떻게 하면 하나의 클래스로 정의 할수 있을까요? 이와 비슷한 문제를 이전의 "함수 템플릿"에서도 나타나지 않았나요? 그때 어떻게 해결했죠?(생각나지 않는 분들은 앞의 "함수 템플릿"을 다시 한번 봐 주세요 ^^)

템플릿으로 하면됩니다.

기능은 같지만 변수의 자료형만 다른 함수를 템플릿을 사용하여 하나의 함수로 정의했듯이 이번에는 템플릿을 사용하여 클래스를 정의합니다. 클래스에서 템플릿을 사용하면 이것을 클래스 템플릿이라고 합니다.

클래스 템플릿을 사용하면 위에서 중복된 클래스를 하나의 클래스로 만들 수 있습니다.

클래스 템플릿을 사용하는 방법

클래스 템플릿을 정의하는 문법은 아래와 같습니다.

그림2

정의한 클래스 템플릿을 사용하는 방법은 아래와 같습니다.

그림3 


....


Stack 템플릿 클래스

지금까지 만들었던 ExpStack 과 MoneyStack을 클래스 템플릿으로 만든 코드는 아래와 같습니다.

const int MAX_COUNT = 100;

template <typename T> 
class Stack
{
public:
  Stack()
  {
    Clear();
  }

  // 초기화 한다.
  void Clear()
  {
    m_Count = 0;
  }

  // 스택에 저장된 개수
  int Count()
  {
    return m_Count;
  }

  // 저장된 데이터가 없는가?
  bool IsEmpty()
  {
    return 0 == m_Count ? true : false;
  }

  // 데이터를 저장한다.
  bool push( T data )
  {
    // 저장 할수 있는 개수를 넘는지 조사한다.
    if( m_Count >= MAX_COUNT )
    {
      return false;
    }

    // 저장후 개수를 하나 늘린다.
    m_aData[ m_Count ] = data;
    ++m_Count;

    return true; 
  }

  // 스택에서 빼낸다.
  T pop()
  {
    // 저장된 것이 없다면 0을 반환한다.
    if( m_Count  < 1 )
    {
      return 0;
    }

    // 개수를 하나 감소 후 반환한다.
    --m_Count;
    return m_aData[ m_Count ];
  }

private:
  T  m_aData[MAX_COUNT];
  int    m_Count;
};

#include 

using namespace std;

void main()
{
  Stack<float> 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<__int64> 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;
  }
}
실행 결과

그림4

클래스 템플릿으로 Stack을 구현하여 앞으로 다양한 데이터를 사용할 수 있게 되었습니다.

...


위의 것은 기본형이고 기본 기능만 내장된거 같나...???????


...

그래서 부족한 점들을 채워 보자..........


.............

클래스 템플릿에서 non-type 파라메터 사용

위에서 만든 Stack 클래스는 데이터를 저장할 수 있는 공간이 100개로 정해져 있습니다.

Stack의 크기는 사용하는 곳에 따라서 변동될 수 있어야 사용하기에 적합합니다.

함수 템플릿을 설명할 때도 non-type이 나왔는데 사용 방법이 거의 같습니다. 템플릿 파라메터를 기본 데이터 형으로 합니다. 아래의 사용 예를 보시면 금방 이해가 갈 것입니다.

// 템플릿 파라메터중 int Size가 non-type  파라메터입니다.
template<typename T, int Size> 
class Stack
{
public:
  Stack()
  {
    Clear();
  }
...
 

템플릿 파라메터 디폴트 값 사용

일반 함수에서 함수 인자의 디폴트 값을 지정하듯이 클래스 템플릿의 파라메터도 디폴트 값으로 할 수 있습니다.

// 템플릿 파라메터중 int Size가 non-type 파라메터입니다. 
// Size의 디폴트 값을 100으로 합니다.
template<typename T, int Size=100> 
class Stack
...
 

스택 클래스의 크기를 클래스 생성자에서 지정

클래스 템플릿에 대한 설명을 계속 하기 위해 현재까지 만든 스택 클래스를 변경합니다. 스택의 크기를 클래스 템플릿 파라메터가 아닌 생성자에서 지정하도록 변경하겠습니다.

template<typename T, int Size=100> 
class Stack
{
public:
  explicit Stack( int size )
  {
    m_Size = size;
    m_aData = new T[m_Size];

    Clear();
  }
...
 

클래스 템플릿 전문화

기획팀에서 새로운 요구가 들어왔습니다. 이번에는 게임을 할 때 같이 게임을 했던 유저의 아이디를 저장하여 보여주기를 원합니다. 지금까지 만든 Stack 클래스는 기본 자료형을 사용하는 것을 전제로 했는데 유저의 아이디를 저장하려면 문자열이 저장되어야 하므로 사용할 수가 없습니다. 

기본 자료형으로 하지 않고 문자열을 사용한다는 것만 다르지 작동은 비슷하므로 Stack이라는 이름의 클래스를 사용하고
싶습니다. 
 
기존의 Stack 클래스 템플릿과 클래스의 이름만 같지 행동은 다른 Stack 클래스를 구현 하려고 합니다. 
이때 필요한 것인 클래스 템플릿의 전문화라는 것입니다. 
 
클래스 템플릿 전문화는 기존에 구현한 클래스 템플릿과 
이름과 파라메터 개수는 같지만 파라메터를 특정한 것으로 지정합니다. 

전문화된 클래스 템플릿 정의는 다음과 같은 형태를 가진다.
 
template <> 
class 클래스 이름<지정된 타입>
{
   ……………….
};
아래의 코드는 문자열을 저장하기 위해 char* 으로 전문화한 Stack 클래스입니다. 

// ID 문자열의 최대 길이(null 문자포함)
const int MAX_ID_LENGTH = 21;

// char* 를 사용한 Stack 클래스(List 6) 템플릿 전문화
template<> 
class Stack
{
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();
  }
...
 

클래스 템플릿 부분 전문화

클래스 템플릿은 템플릿 파라메터 중 일부를 구체적인 형(type)을 사용, 또는 템플릿 파라메터를 포인터나 참조를 사용하여 부분 전문화를 할 수 있습니다.

- 구체적인 형 사용에 의한 부분 전문화
template< typename T1, typename T2 > class Test { …. };
의 T2를 float로 구체화 하여 부분 전문화를 하면 다음과 같습니다.
template< typename T1 > class Test { ….. };
코드는 다음과 같습니다.

template< typename T1, typename T2 >
class Test
{
public:
  T1 Add( T1 a, T2 b )
  {
    cout << "일반 템플릿을 사용했습니다." << endl;
    return a;
  }
};

// T2를 float로 구체화한 Test의 부분 전문화 템플릿
template< typename T1 > 
class Test
{
public:
  T1 Add( T1 a, float b )
  {
    cout << "부분 전문화 템플릿을 사용했습니다." << endl;
    return a;
  }
};

#include 

using namespace std;

void main()
{
  Test test1;
  test1.Add( 2, 3 );

  Test test2;
  test2.Add( 2, 5.8f );
}
그림9
..
 

싱글톤 템플릿 클래스

클래스 상속을 할 때 템플릿 클래스를 상속 받음으로 상속 받는 클래스의 기능을 확장할 수 있습니다. 

저의 경우 현업에서 클래스 템플릿을 가장 많이 사용하는 경우가 클래스 템플릿을 사용한 싱글톤 클래스
템플릿을 사용하는 것입니다. 

어떠한 객체가 꼭 하나만 있어야 되는 경우 싱글톤으로 정의한 클래스 템플릿을 상속 받도록 합니다.
싱글톤은 
싱글톤 패턴을 말하는 것으로 어떤 클래스의 인스턴스가 꼭 하나만 생성되도록 하며, 
전역적인 접근이 가능하도록 합니다. 어떤 클래스를 전역으로 사용하는 경우 복수개의 인스턴스가 생성되지 않도록 싱글톤 패턴으로 생성하는 것을 권장합니다.
사용하는 방법은 베이스 클래스를 템플릿을 사용하여 만듭니다. 그리고 이것을 상속 받는 클래스에서 
베이스 클래스의 템플릿 파라메터에 해당 클래스를 사용합니다. 즉 싱글톤 클래스 템플릿은 이것을 상속 받는 
클래스를 싱글톤으로 만들어줍니다. 

위에서 설명한 클래스 템플릿에 대하여 이해를 하셨다면 의 코드를 보면 이해를 할 수 있으리라 생각합니다.
싱글톤 클래스 템플릿은 직접 생성을 하지 않으므로 주 멤버들을 static로 만들어줍니다. 
그리고 생성자를 통해서 _Singleton를 생성하지 않고 GetSingleton()을 통해서만 생성하도록 합니다. 

#include 
using namespace std;


// 파라메터 T를 싱글톤이 되도록 정의 합니다.
template <typename T>
class MySingleton
{
public:
    MySingleton() {}
    virtual ~MySingleton() {}

    // 이 멤버를 통해서만 생성이 가능합니다.
    static T* GetSingleton()
    {
        // 아직 생성이 되어 있지 않으면 생성한다.
        if( NULL == _Singleton ) {
            _Singleton = new T; 
        }

       return ( _Singleton );
    }

    static void Release()
    {
        delete _Singleton;
        _Singleton = NULL;
    }

private:
    static T* _Singleton;
};

template <typename T> T* MySingleton ::_Singleton = NULL;

// 싱글톤 클래스 템플릿을 상속 받으면서 파라메터에 본 클래스를 넘깁니다.
class MyObject : public MySingleton
{
public:
MyObject() : _nValue(10) {}

void SetValue( int Value ) { _nValue = Value;}  
int GetValue() { return _nValue; }

private :
int _nValue;
};

void main()
{
   MyObject* MyObj1 = MyObject::GetSingleton();

   cout << MyObj1->GetValue() << endl;

   // MyObj2는 Myobj1과 동일한 객체입니다.
   MyObject* MyObj2 = MyObject::GetSingleton();
   MyObj2->SetValue(20);

   cout << MyObj1->GetValue() << endl;
   cout << MyObj2->GetValue() << endl;
}

'온라인게임 > stl' 카테고리의 다른 글

Standard Template Library (STL), 1 of n  (0) 2010.10.07
함수 템플릿 Template 2-1  (0) 2010.10.01
STL이 무엇인지 알고 계십니까? 1  (0) 2010.10.01

제공: 한빛 네트워크
저자: 최흥배
이전기사:

함수 템플릿

두 값을 비교하는 함수를 만들어야 됩니다.

HP를 비교하는 두 개의 int 타입을 비교하는 Max라는 이름의 함수를 하나 만들었습니다.
int Max( int a, int b );

일을 다 끝낸 후 다음 기획서를 보니 캐릭터와 NPC가 전투를 하는 것을 구현해야 되는데
여기에는 경험치 비교하는 기능이 필요합니다.
구현해야 되는 것은 위에서 만든 Max 함수와 같습니다. 그래서 그것을 사용하였습니다.

< List 1 >

#include 
using namespace std;

int Max( int a, int b )
{
  return a > b ? a : b;
}

void main()
{
  int Char1_HP = 300;
  int Char2_HP = 400;
  int MaxCharHP = Max( Char1_HP, Char2_HP );
  cout << "HP 중 가장 큰 값은" << MaxCharHP << "입니다." << endl << endl;
  
  float Char1_Exp = 250.0f;
  float Char2_Exp = 250.57f;
  float MaxCharExp = Max( Char1_Exp, Char2_Exp );
  cout << "경험치 중 가장 큰 값은" << MaxCharExp << "입니다." << endl << endl;
}
앗, 체력(HP)을 저장하는 변수의 타입은 int인데, 경험치 저장하는 변수의 타입은 int가 아닌 float 타입니다. 

 

당연하게 경험치를 비교하는 부분은 버그가 있습니다.
앞에 만들었던 Max와는 다르게 비교하는 변수의 타입이 float인 것이 필요하여 새로 만들었습니다.

< List 2 >
float Max( float a, float b )
{
  return a > b ? a : b;
}
함수 오버로딩에 의해 경험치를 비교할 때는 int 타입의 Max가 아닌 의 float 타입을 비교하는 Max가 호출되어 버그가 사라지게 되었습니다.

이제 경험치 비교는 끝나서 다음 기획서에 있는 것을 구현해야 합니다.

이번에는 을 비교하는 것이 있습니다. 그런데 돈을 저장하는 변수의 타입은 __int64입니다.
__int64는 비주얼 C++에서만 사용할 수 있는 64비트 정수 타입입니다.
__int64 타입을 비교하는 것은 앞에서 만든 int 타입의 Max나 float 타입의 Max로 할 수 없습니다.
함수에서 사용하는 변수의 타입만 다를 뿐 똑같은 것을 또 만들어야 됩니다.
__int64 Max(__int64 a, __int64 b )
{
  return a > b ? a : b;
}
현재까지만 하더라도 이미 똑같은 로직으로 구현된 함수를 3개나 만들었는데, 게임에서 사용하는 캐릭터의 정보는 HP, 경험치, 돈 이외에도 더 많습니다. 저는 앞으로 Max 함수를 몇 개 더 만들어야 할지 모릅니다.

Max 함수의 구현을 고쳐야 한다면 모든 Max 함수를 찾아야 합니다. 함수 오버로딩은 문제를 해결하지만, 코드가 커지고 유지보수는 어렵게 만듭니다.

프로그래밍에서 유지보수는 아주 중요합니다. 왜냐하면, 프로그래밍은 언제나 변경이 가해지기 때문입니다. 유지보수를 편하게 하는 가장 간단한 방법은 유지보수 할 것을 줄이는 것입니다.

Max 함수를 하나로 만들고 싶습니다. 어떻게 해야 될까요?

앗, 혹시 모른다고요? 제가 이 앞에 템플릿에 대해 설명을 할 때 이런 말을 하지 않았나요?
'템플릿을 사용하면 타입에 제약을 받지 않는 로직을 기술 할 수 있습니다'
네, 템플릿을 사용하면 됩니다.

함수 템플릿 Max를 만들자

아래의 코드는 템플릿을 사용하여 Max 함수를 구현 한 것입니다.

< List 3 >
#include 
using namespace std;

// 템플릿으로 만든 값을 비교하는 Max 함수
template 
T Max(T a, T b )
{
  return a > b ? a : b;
}


void main()
{
  int Char1_HP = 300;
  int Char2_HP = 400;
  int MaxCharHP = Max( Char1_HP, Char2_HP );
  cout << "HP 중 가장 큰 값은" << MaxCharHP << "입니다." << endl << endl;
  
  float Char1_Exp = 250.0f;
  float Char2_Exp = 250.57f;
  float MaxCharExp = Max( Char1_Exp, Char2_Exp );
  cout << "경험치 중 가장 큰 값은" << MaxCharExp << "입니다." << endl << endl;
}
실행한 결과는 다음과 같습니다. 

 

네 이번에는 경험치 비교가 정확하게 이루어졌습니다.
템플릿을 사용하게 되어 이제는 불필요한 Max 함수를 만들지 않아도 됩니다..

<List 3> 코드에서 template으로 만든 함수를 '함수 템플릿'이라고 합니다.



함수 템플릿을 정의하는 방법은 아래와 같습니다. 

 

...

함수 템플릿과 컴파일

하나의 Max 함수 템플릿을 만들었는데 어떻게 int 타입의 Max와 float 타입의 Max를 사용할 수 있을까요? 비밀은 컴파일하는 과정에 있습니다. 컴파일할 때 템플릿으로 만든 것은 템플릿으로 만든 함수를 호출하는 부분에서 평가합니다. 가상 함수처럼 실행시간에 평가하는 것이 아닙니다.

컴파일을 할 때(compile time) 함수 템플릿을 평가하므로 프로그램의 성능에 해가 되는 것은 없습니다.

...




  • About STL : C++ STL 프로그래밍(2-2)
  • About STL : C++ STL 프로그래밍(3)
  • About STL : C++ STL 프로그래밍(4)
  • About STL : C++ STL 프로그래밍(5-1)
  • About STL : C++ STL 프로그래밍(5-2)
  • About STL : C++ STL 프로그래밍(6)
  • About STL : C++ STL 프로그래밍(7)
  • About STL : C++ STL 프로그래밍(8)
  • About STL : C++ STL 프로그래밍(9)
  • About STL : C++ STL 프로그래밍(10)
  • #include 
    using namespace std;
    
    /*
    int Max( int a, int b )
    {
      return a > b ? a : b;
    }
    float Max( float a, float b )
    {
      return a > b ? a : b;
    }
    
    __int64 Max(__int64 a, __int64 b )
    {
      return a > b ? a : b;
    }
    */
    template  T Max( T a, T b)
    {
    	return a>b ? a : b;
    }
    
    void main()
    {
      int Char1_HP = 300;
      int Char2_HP = 400;
      int MaxCharHP = Max( Char1_HP, Char2_HP );
      cout << "HP 중 가장 큰 값은" << MaxCharHP << "입니다." << endl << endl;
      
      float Char1_Exp = 250.0f;
      float Char2_Exp = 250.57f;
      float MaxCharExp = Max( Char1_Exp, Char2_Exp );
      cout << "경험치 중 가장 큰 값은" << MaxCharExp << "입니다." << endl << endl;
    }
    

    Max 함수 템플릿에 개선점이 없을까요?

    힌트를 드린다면 Max의 두 인자 값은 함수 내부에서 변경되지 않습니다. 그리고 인자의 타입은 C++의
    기본형뿐만이 아닌 크기가 큰 타입을 사용할 수도 있습니다.
    생각나셨나요? C++ 기초 공부를 차근차근 쌓아 올린 분이라면 알아차렸으리라 생각합니다.
    정답은 Max 함수 템플릿을 만들 때 템플릿의 인자에 const와 참조를 사용하는 것입니다. Max 함수는 함수의 내부에서 함수의 인자를 변경하지 않습니다. 그러니 함수에 const를 사용하여
    내부에서 변경하는 것을 명시적으로 막고 Max 함수를 사용하는 사람에게 알리는 역할을 합니다.
    C++에서 함수 인자의 전달을 빠르게 하는 방법은 참조로 전달하는 것입니다.
    위의 Max 함수는 int나 float 같은 크기가 작은 타입을 사용하였기 때문에 참조로 전달하는 것이
    큰 의미는 없지만, 만약 구조체나 클래스로 만들어진 크기가 큰 변수를 사용할 때는 참조로 전달하는 것이
    훨씬 빠릅니다. 앞에 만든 Max 함수 템플릿을 const와 참조를 사용하는 것으로 바꾸어 보았습니다.
    template <typename T> const T& Max(const T& a, const T& b ) { return a > b ? a : b; }

    함수 템플릿의 전문화 라는 것이 있습니다.

    Max(int, double)을 사용하면 Max 함수 템플릿이 아닌 이것에 맞는, 특별하게 만든 함수를 사용하도록 합니다. 함수 템플릿의 전문화(Specialization)라는 특별한 상황에 맞는 함수를 만들면 함수 오버로드와 같이 컴파일러가 상황에 맞는 함수를 선택하도록 합니다.

    < List 8 >
    #include 
    using namespace std;
    
    // 템플릿으로만든값을비교하는Max 함수
    template <typename T1, typename T2> 
    const T1& Max(const T1& a, const T2& b )
    {
      cout << "Max(const T& a, const T& b) 템플릿 버전 사용" << endl;
      return a > b ? a : b;
    }
    
    // 전문화시킨Max 함수
    template <> 
    const double& Max(const double& a, const double& b)
    {
      cout << "Max(const double& a, const double& b) 전문화 버전 사용" << endl;
      return a > b ? a : b;
    }
    
    void main()
    {
      double Char1_MP = 300;
      double Char1_SP = 400.25;
      double MaxValue1 = Max( Char1_MP, Char1_SP );
      cout << "MP와 SP 중 가장 큰 값은" << MaxValue1 << "입니다." << endl << endl;
      
      int Char2_MP = 300;
      double Char2_SP = 400.25; 
      double MaxValue2 = Max( Char2_MP, Char2_SP );
      cout << "MP와 SP 중 가장 큰 값은" << MaxValue2 << "입니다." << endl << endl;
    }
    위 코드를 실행한 결과는 아래와 같습니다. 

    '온라인게임 > stl' 카테고리의 다른 글

    Standard Template Library (STL), 1 of n  (0) 2010.10.07
    클래스 템플릿 2-2  (0) 2010.10.01
    STL이 무엇인지 알고 계십니까? 1  (0) 2010.10.01

    제공: 한빛 네트워크
    저자: 최흥배

    http://www.hanb.co.kr/network/view.html?bi_id=1563

    STL이 무엇인지 알고 계십니까?

    STL은 C++ 언어의 '표준 템플릿 라이브러리 (Standard Template Library) '의 약자입니다.

    STL을 자료구조와 알고리즘 모음 라이브러리

    STL은  1993년 말 무렵에 Alex Stepanov가 C++ 언어의 창시자인 Bjarne Stroustrup에게 보여준 후
    준비 기간을 걸쳐서 1994년에 표준 위원회에 초안이 통과됩니다.

    참고로 C++ 표준은 1989년에 시작되어 1998년 9월에 마무리되었습니다.

    STL은 어떻게 만들었을까요?

    템플릿(Template)으로 만들어 진 것입니다.

    STL을 이해하려면 STL을 만들 수 있게 해준 C++의 템플릿에 대한 이해는 필수입니다.
    또, 템플릿은 C++를 더욱 강력하게 사용하는 데 꼭 필요합니다.

    C++ 언어를 공부한 사람은 템플릿에 대해 잘 알고 있을까요?


    1994년까지는 템플릿을 지원하는 C++ 컴파일러가 없었고, MS의 C++ 툴로 유명한 Visual C++도 버전 6에서는 템플릿을 완벽하게 지원하지 못했으면 Visual Studio .NET 2000 에서부터 제대로 지원을 하게 되었습니다(아직도 템플릿 기능을 100% 완벽하게 지원하지는 못합니다.).

    개인적으로 C 언어를 생각하면 포인터가 떠오르고, C++ 언어를 생각하면 클래스와 템플릿이 떠올라집니다.

    포인터는 처음 배울 때 문법적인 사용 방법이 잘 이해가 안 돼서 어려웠지만,
    클래스나 템플릿은 프로그램 설계와 관계된 것들이라 사상 부분을 이해하기 어려웠습니다.

    객체 지향 프로그래밍(OOP) C++

    C++ 언어를 소개할 때 가장 먼저 이야기하는 것이 객체지향이라는 것입니다.

    보통 C 언어를 배운 후 바로 이어서 C++를 배울 때는 객체 지향 프로그래밍(Object-Oriented Programming)에 대한 이해가 부족합니다. 그래서 C 언어로 프로그래밍할 때와 같은 절차 지향 프로그래밍을 하여 이른바 'C++를 가장한 C 프로그래밍'을 한다는 소리를 듣기도 합니다.

    C++ 언어로 객체 지향 프로그래밍을 할 수 있는 것은 C 언어에는 없는 클래스가 있기 때문입니다.

    [질문] C++로 할 수 있는 프로그래밍 스타일은 절차적 프로그래밍, 객체 지향 프로그래밍만 있을까요?
    [답] 아니오. Generic Programming 도 가능합니다.

    Generic Programming 이라는 것을 들어 보셨나요?

    책에서는 언제나 OOP 단어는 무수히 많이 보았지만, Generic Programming이라는 단어를 그 당시에 본 기억이 없습니다. 제가 Generic Programming이라는 단어를 알게 된 것은 2001년 무렵입니다. C++ 언어를 공부한 지 거의 6년이 되어서야 알게 되었습니다.

    아마 지금 공부하시는 분들도 Generic Programming이라는 단어는 좀 생소할 것입니다.

    Generic Programming은 한국에서는 보통 '일반적 프로그래밍'이라고 이야기 합니다. 저도 처음에는 그렇게 들었습니다.

    그러나 이것은 잘못된 표현이지 않을까 생각합니다. 영어 사전을 보면 Generic 이라는 것은 '총칭(總稱)적인' 이라는 뜻도 있는데 이것이 '일반적'이라는 단어보다 더 확실하며 제가 2004년에 일본에서 구입한 "C++ 설계와 진화(Bjarne Stroustrup 저)"라는 일본 번역서에도 Generic은 총칭으로 표기하고 있습니다.

    그럼 Generic Programming은 무엇일까요?

    네이버 사전에서 Generic 이라는 단어를 검색하면,

    3【문법】 총칭적인
    the generic singular 총칭 단수 《보기:The cow is an animal.》

    라는 부분이 있습니다. 보기의 영문을 저의 짧은 영어 실력으로 번역을 하면 '암소는 동물이다' 입니다. 소는 분명히 고양이나 개와는 다른 동물이지만 '동물'이라는 것으로 총칭할 수 있습니다.

    대체 C++언어에서 무엇을 '총칭'화 할까요?

    제가 만드는 프로그램은 Windows 플랫폼에서 실행되는 '온라인 게임 서버' 프로그램입니다.

    온라인 게임 서버를 만들 때는 어떤 기능이 있어야 되는가를 정한 후 클래스를 만듭니다.

    클래스는 아시는 바와 같이 멤버 변수와 멤버 함수로 이루어져 있습니다.
    그리고 멤버 함수도 그 내용은 저의 생각에 의해 변수들이 조작으로 되어 있습니다.

    '암소는 동물이다'라는 식으로 C++ 언어에서 총칭을 하는 것은 변수의 타입(type)을 총칭화 하는 것입니다.
    • 템플릿을 이용하면 총칭화된 타입을 사용하는 클래스와 함수를 만들 수 있습니다.
    • 템플릿을 사용하면 타입에 제약을 받지 않는 로직을 기술 할 수 있습니다.
    • Generic Programming을 하기 위해서는 템플릿이 꼭 필요합니다.
    STL이 무엇으로 만들어졌나요? 네 템플릿으로 만들어졌습니다.
    STL은 Generic Programming으로 만들어진 가장 대표적인 예입니다.

    긴 설명은 그만하고 코드를 볼까요?

    제 나름대로 템플릿을 이해하는 데 도움이 되었으면 해서 이런저런 이야기를 했는데 과연 도움이 되었는지 모르겠네요. 아마 설명만 듣고서는 템플릿에 대해 명확하게 이해를 하지 못하리라 생각합니다. 우리 프로그래머들은 정확하게 이해하려면 코드를 봐야겠죠? 템플릿은 크게 함수 템플릿과 클래스 템플릿으로 나눌 수 있습니다.

    다음 시간에는 함수 템플릿에 대해서 이야기하겠습니다.


  • About STL : C++ STL 프로그래밍(2-1)
  • About STL : C++ STL 프로그래밍(2-2)
  • About STL : C++ STL 프로그래밍(3)
  • About STL : C++ STL 프로그래밍(4)
  • About STL : C++ STL 프로그래밍(5-1)
  • About STL : C++ STL 프로그래밍(5-2)
  • About STL : C++ STL 프로그래밍(6)
  • About STL : C++ STL 프로그래밍(7)
  • About STL : C++ STL 프로그래밍(8)
  • About STL : C++ STL 프로그래밍(9)
  • About STL : C++ STL 프로그래밍(10)
  • '온라인게임 > stl' 카테고리의 다른 글

    Standard Template Library (STL), 1 of n  (0) 2010.10.07
    클래스 템플릿 2-2  (0) 2010.10.01
    함수 템플릿 Template 2-1  (0) 2010.10.01

    + Recent posts