내장형 하드웨어/C++

C++ - 템플릿(template)

동화다아아 2011. 11. 21. 15:54

- 템플릿(tempate)
 → 모든 형을 다 선언할 수 있는 클래스
 → template <class T> 와 같은 형태로 선언한다.
#include<iostream.h>

template
 <class T>
class array
{
  private:
    T *item;
    int iNum;
    array() // 디폴트 생성자
    {
      
    }
    array(array &r) // 복사 생성자
    {
                
    }
    array& operator =(array &r) // 대입 연산자
    {
      return *this;      
    }    
  public:
    array(int iNum) // 인자가 하나인 생성자
    {      
      this->iNum = iNum;
      item = new T[iNum];
      for(int iCnt = 0; iCnt<iNum; ++iCnt)
      {
        item[iCnt] = 0;
      }      
      cout << "인자가 1개인 array 생성자" << endl;
    }    
    void print();// print()      
    
    ~array() // 소멸자
    {
      delete [] item;
      cout << "array 소멸자 " << endl;
    }  
    // T는 컴파일하면 int로 바뀐다.
    // main()에서 <int> 선언했기 때문
    void setMember(int iNum, T value)
    {
      if(this->iNum<=iNum)
      {
        return ;
      }
      // iNum 자리(배열)의 값을 value로 바꾼다. 
      item[iNum] = value;
        
      return ;
    }
};
template <class T>
void array<T>::print() // print()      
{
  for(int iCnt = 0;iCnt<iNum;++iCnt)
  {
    cout << item[iCnt] << " ";
  }
  cout << endl;
  return ;
}

int main()
{
  array <int> OBJ1(5);
  // 두번째 인자가 int가 아니지만 동작한다.-template
  OBJ1.setMember(32);
  OBJ1.print();
  // <float> 으로 바꾸었다. 
  // 따라서 출력 결과는 item[3]자리에 3.1이 출력된다.
  array <float> OBJ2(6);
  OBJ2.setMember(33.1f);
  OBJ2.print();
  
  return 0;
}

 → array <int> OBJ1(5); 와 같이 선언한다.
 → <int>로 T 부분은 모두 int 형이 된다.
 → <float>로 T 부분은 모두 float 형이 된다.
 → 자료기반의 언어(C 언어)에서 형이 바뀌면 함수를 그대로 복사하여 형을 바꾸는 등으로 사용해야 했다면 template를 사용하여 여러가지 형을 사용할 수 있다.
 → 실행 결과


※ cat main10.cpp >> main11.cpp
 → 리눅스에서 위와 같은 명령으로 main11.cpp 파일의 내용에 main10.cpp의 내용을 추가(덧붙일 수)할 수 있다.

 → template는 클래스도 집어 넣을 수 있다.
 → 즉 모든 클래스를 다 사용할 수 있다.
 → 예로 이전에 emb 클래스를 사용한다. templet을 emb 타입으로 하여 실행시켜 보면

int main()
{
        array <emb> OBJ1(10);
        emb temp;
        temp = 100;

        OBJ1.setMember(3, temp);
        cout << OBJ1 << endl;
        return 0;
}

 → array <emb> OBJ1(10); // 배열 10개를 가지는 객체 생성
 → emb형 temp 변수를 만들어 값을 대입하고 이를 OBJ1.setMember(3, temp); 의 형식으로 입력한다.
 → 실행 결과

 → 실행 결과를 확인해 보면 4번째 emb 멤버 변수 출력에서 값 A, B, C, D가 모두 100으로 바뀐것을 확인할 수 있다.


- 가상함수
// 가상함수
#include<iostream.h>


class Musician
{
  private:

  public:
    // virtual - 각각의 자식 클래스들을 사용하게 해 준다.
    // 오버 라이딩
    virtual void greet() // MFC에서 매우 중요한 기법
    {
      cout << "안녕하세요 저는 뮤지션입니다." << endl;
    }
};
class Singer:public Musician
{
  private:
    
  public:
    void greet()
    {
      cout << "안녕하세요 저는 싱어입니다." << endl;
    }    
};
class Drum:public Musician
{
  private:
    
  public:
    void greet()
    {
      cout << "안녕하세요 저는 드러머입니다." << endl;
    }
};
class Bell:public Musician
{
  private:
    
  public:
    void greet()
    {
      cout << "안녕하세요 저는 벨 연주자입니다." << endl;
    }
};

int main()
{
  Musician M;
  Singer S;
  Drum D;
  Bell B;
  Musician *P[4= {&M, &S, &D, &B}; // 각각을 초기화
  
  for(int iCnt = 0 ; 4>iCnt ; ++iCnt)
  {
    (*P[iCnt]).greet();
  }
  
  
/*
  M.greet();
  S.greet();
  D.greet();
  B.greet();
  */

  return 0;
}

 → 최상위 클래스인 Musician의 중복 사용을 위한 void greet(); 앞에 virtual을 붙여준다.
 → virtual void grret();
 → 이렇게 하면 클래스 포인터 타입인 Musician의 greet() 함수만 출력되던 결과가 전체 상속받은 클래스들의 값들로 바뀌어 출력되는 것을 확인 할 수 있다.
 → 즉, 부모 포인터를 가지면 부모만 출력되던 결과에서 virtual을 사용하므로서 자식들을 각각 가리켜 출력되게 한다.