Recent Posts
Recent Comments
Link
«   2025/01   »
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
Archives
Today
Total
관리 메뉴

3냥 집사이면서 게임 개발자입니다.

[전문가를 위한 C++] 메서드 템플릿 본문

CPPTMP

[전문가를 위한 C++] 메서드 템플릿

훙이야 2024. 11. 28. 13:46

메서드 템플릿은 클래스 템플릿 안에 정의해도 되고 비템플릿 클래스 안에 정의해도 된다.

메서드 템플릿은 클래스 템플릿에 복제 생성자와 대입 연산자를 정의할 때 특히 유용하다.

* 가상 메서드와 소멸자는 메서드 템플릿으로 만들 수 없다.

 

간단한 예시 

Grid<int> IntGrid;

Grid<double> DoubleGrid;

이렇게 만든 두 변수는 타입이 서로 다르다.

Grid <double>객체를  받는 함수는 Grid<int> 객체를 인수로 받을 수 없다.

int 를 double로 강제 형변환해서 int원소를 double원소로 복제할 수는 있지만, 위 객체끼리는 대입하거나 변환이 불가능하다.

따라서 다음과 같이 작성하면 컴파일 오류가 발생한다.

DoubleGird = IntGrid;

이유는 Grid 템플릿에 대한 복제 생성자와 대입 연산자를 어떻게 정의했는지에서 파악해야한다.

 

Grid(const Grid& src);

Grid<T>& operator=(const Grid& rhs);

이를 정확히 표현하면

Grid(const Grid<T>& src);

Grid<T>& operator=(const Grid<T>& rhs);

와 같다.

그러므로 Grid<double> 을 인스턴스화해서 Grid 복제 생성자와 operator= 을 호출하면 컴파일러는 각각에 대한 프로토 타입을 다음과 같이 생성한다.

 

Grid(const Grid<double>& src);

Grid<double>& operator=(const Grid<double>& rhs);

생성된 Gird<double>클래스에는 Grid<int>를 받는 생성자나 operator= 이 없다.

이를 메서드 템플릿으로 서로 다른 타입을 처리할 수 있다. 

// 생략

// 1.
template <typename E>
Grid(const Grid<E>& src);

// 2.
template <typename E>
Grid<T>& operator=(const Grid<E>& rhs);

void swap(Grid& other) noexcept;

// 생략

 

1. 템플릿 버전으로 수정한 복제 생성자

클래스는 T라는 타입에 대해 템플릿화되고, 수정한 복제 생성자는 E라는 타입에 대해 템플릿화 된다.

두 타입에 대해 템플릿화함으로써 한 타입의 Gird 객체를 다른 타입의 Grid로 복제할 수 있다.

template <typename T>
template <typename E>
Grid<T>::Grid(const Grid<E>& src) : Grid(src.getWidth(), src.getHeight())
{
 // 이 생성자의 생성자 이니셜라이저는 적절한 양의 메모리를 할당하는 작업을 비복제 생성자에 위임한다.

// 그리고 나서 데이터를 복제한다.

  for(size_t i = 0; i < mWidth; i++)
   {
      for(size_t j = 0; j < mHeight; j++)
         {
            mCells[i][j] = src.at(i,j);
         }
   }
}

복제 생성자를 정의하는 코드다. 

클래스 템플릿 선언문(T 매개변수가 있는)을 먼저 적고, 그 뒤에 멤버 템플릿(E 매개변수를 가진)을 선언하는 문장을 따로 작성해야 한다. 두 문장을 합쳐서 작성하면 안된다. (template <typename T, typename E>)

 

2. 템플릿화한 대입 연산자는 const Grid<E>& 타입의 인수를 받아서 Grid<T>& 타입을 리턴한다.

 

template <typename T>
template <typename E>
Grid<T>& Grid<T>::operator=(const Grid<E>& rhs)
{
	// 자기 자신을 대입할 경우에 대한 예외 처리를 할 필요가 없다.
    // 이 버전의 대입 연산자는 T와 E가 같으면 호출되지 않는다.
    
    // 복제후 바꾸기
    Grid<T> temp(ths); // 모든 작업을 임시 인스턴스에서 처리 
    swap(temp); // noexept 키워드를 사용한 swap 함수
    return *this;
}

 

템플릿화한 대입 연산자는 먼저 템플릿화한 복제 생성자를 이용해 Grid<E>객체를 Grid<T> 객체(temp) 로 변환한다.

그리고 swap메서드로 Grid<T> 타입인 temp 를 this와 맞바꾼다. 

'CPPTMP' 카테고리의 다른 글

[전문가를 위한 C++] 클래스 템플릿  (0) 2024.11.28