업데이트:

태그: ,

카테고리:



REF : 윤성우의 열혈 C++

함수템플릿

  • 함수템플릿은 다양한 자료형의 함수를 만들어낼 수 있다.
    1.   int Add(int num1, int num2)
        {
            return (num1 + num2);
        }
      

      위와같은 함수는

    2.   template <typename T>
        T add(T num1, T num2)
        {
            return (num1 + num2);
        }
      

      이렇게 함수템플릿으로 선언할 수 있다.

  • template <typename T>대신, template <class T>로도 선언할 수 있다.

  • 실제로 위 함수가 사용되는 예시는 아래와 같다.
      int main(void)
      {
          cout<<Add<int>(15, 20) <<endl;
          cout<<Add<double>(2.9, 3.7) <<endl;
          cout<<Add<int>(3, 3) <<endl;
          cout<<Add<double>(3.14, 2.75) <<endl;
          return (0);
      }
    
  • 함수 호출 시, 함수와 매개변수 사이에 <변환될 자료형>을 넣어줄수도 있다.
  • 넣지않는다면, 컴파일러가 자료형으로 알아서 변환한다.
  • 컴파일러가 자료형으로 만드는 함수를 템플릿 함수라고한다.
  • 또는, 생성된 함수라고도 불린다.


둘 이상의 형에 대해 템플릿 선언

  • 템플릿의 정의에 다양한 자료형도 선언할 수 있다.
  • 둘 이상의 형에 대해서 템플릿을 선언할 수 있다.
template <class T1, class T2>
void ShowData(double num)
{
	cout<<(T1)num<<", "<<(T2)num<<endl;
}

int main(void)
{
	ShowData<char, int>(65);
	ShowData<char, int>(67);
	ShowData<char, double>(68.9);
	ShowData<short, double>(69.2);
	ShowData<short, double>(70.4);
	return 0;
}


함수 템플릿의 특수화

  • 템플릿 함수를 상황에따라 다르게 구성해야할수도 있다.
  • 단순히 크기 비교가 아닌, 문자열의 길이를 비교한다던지,
  • 사전편찬 순으로 비교한다던지를 하기위해서는 함수 템플릿 특수화를 해야한다.
template<>
char *Max<char *>(char *a, char *b)
{
	return (strlen(a) > strlen(b) ? a : b)
}

template<>
const char *Max<const char *>(const char *a, const char *b)
{
	return (strcmp(a, b)> 0 ? a : b);
}
  • 컴파일러에게 특수화할 자료형의 함수를 전달해 해당 자료형의 경우에는 정의한 함수를 사용하도록한다.



클래스 템플릿

  • 함수를 템플릿으로 정의했듯, 클래스도 템플릿으로 정의할 수 있다.
  • 이렇게 정의된 템플릿을 클래스 템플릿, 이를 바탕으로 만들어진 클래스를 템플릿 클래스라고한다.


클래스 템플릿의 정의

  • 저장하는 멤버변수가 다르다는 이유만으로 유사한 클래스를 여러개 정의하는 것은 비효율적이다.
  • 이때 사용되는게 클래스 템플릿이다.

  • 정수형 좌표를 저장하는 클래스 예시
      class Point
      {
          private :
              int x;
              int y;
          public:
              Point(int x, int y) : x(x), y(y)
              {}
              void ShowPosition() const
              {
                  ...
              }
      };
    

내부 멤버변수가 float, char * 등등인 경우에 클래스를 각각 생성하는건 비효율적이다.
이때, 클래스 템플릿을 사용한다.

template <typename T>
class Point
{
	private:
		T x;
		T y;
	public:
		Point(T x, T y) : x(x), y(y)
		void ShowPosition() const
		{
			...
		}
};
  • 컴파일러는 클래스 템플릿을 기반으로 템플릿 클래스를 만들어낸다.
  • 필요한 템플릿 클래스를 만들어서 객체를 생성해낸다.
  • 단, 클래스 템플릿은 반드시 객체생성시 자료형을 명시해야한다.


클래스 템플릿의 몸체 분리

  • 위의 Point 클래스 템플릿의 몸체를 분리해보자.
template <typename T>
class Point
{
	private:
		T x;
		T y;
	public:
		Point(T x, T y);
		void ShowPosition() const;
};

template <typename T>
Point<T>::Point(T x, T y) : x(x), y(y)
{}

template <typename T>
void Point<T>::ShowPosition() const
{
	...
}
  • 함수의 몸체에도 template을 선언해주어야 컴파일러가 잘 인식한다.


클래스 템플릿으로 템플릿 클래스의 객체를 담는 객체 생성

  • 클래스 템플릿을 정의하면 어느 자료형이든 받을 수 있다.
  • 이에는 다른 클래스 템플릿으로 정의되어 생성된 템플릿 클래스도 담길 수 있다.
BoundCheckArray<int> iarr[50]; //int형 자료형을 담을 수 있다.
BoundCheckArray<Point<int>> parr[50]; //Point<int> 템플릿 클래스의 객체도 담을 수 있다.
BoundCheckArray<Point<int>*> parr[50]; //Point<int> 템플릿 클래스의 객체의 포인터도 담을 수 있다.


클래스 템플릿의 특수화

  • 함수템플릿을 특수화했듯, 클래스 템플릿도 특수화할 수 있다.
  • 자료형에따라 다른 행동양식을 정하기 위해서사용한다.
template <typename T>
class A
{};

이런 클래스 템플릿에 대한 int 자료형에 대한 특수화는

template <>
class A<int>
{};

이렇게 할 수 있고, 객체를 생성하기 위해선

A<int> obj1;

으로 선언할 수 있다.


템플릿클래스 객체선언

  • 클래스 템플릿을 기반으로한 템플릿 클래스의 객체 선언방법

    • 저장대상이 tc<int>일 경우
        A<tc<int>> obj;
      
    • 저장대상이 tc<int>*일 경우
        A<tc<int> *> obj;
      


특정 템플릿 클래스의 객체를 인자로 받는 일반함수의 정의

댓글남기기