C/C++ 관련 헷갈리기 쉬운 것 정리10(저장용,메모용, 윤성우 열혈 C++ 프로그래밍 정리 CH 13)

RisingJade의 개발기록·2022년 2월 28일
0

윤성우 열혈C++ 정리

목록 보기
10/13

Chapter 13. 템플릿 (Template)


13-1. 템플릿에 대한 이해와 함수 템플릿

함수를 대상으로 템플릿 이해하기

함수 템플릿은 함수를 만들어 낸다. 함수의 기능은 결정되어 있지만, 자료형은 결정되어 있지 않아서 결졍해야 한다.

즉, 함수 템플릿이라는 것은 함수를 만드는 도구가 된다.

template <typename T> // T라는 이름을 이용해서 아래의 함수를 템플릿으로 정의한다는 의미이다.
template <class C> // typename, class 둥다 흔히 사용되니 아무거나 쓰자, C++ 창시자 왈 class가 편하다.(짧아서..)
T Add(T num1, T num2)
{
	return num1 + num2;
}

int main(void){
	Add<int>(14,20);
    Add<double>(2.9, 2.3);//이렇게 <>안에 원하는 타입을 넣어 원하는 방식으로 작동할 수 있따.
}
  • 여기서 함수 템플릿을 통해 만들어진 것은 컴파일 시 Add<int>, Add<double>을 보고 미리 저 타입의 함수를 만들어 둔다. 그리고 나서 런타임시엔 앞서 만들어 놓은 두 함수를 호출 할 뿐이다. 런타임에 새로 함수를 만들지 않으며, 함수는 자료형만 하나씩만 만들어지게 된다.
  • 물론, 컴파일 속도의 감소는 발생하지만 그건 컴파일 속도이지 실행속도가 아니기 때문에 컴파일시간이 아까운 상황이 아니라면 크게 신경 쓸 요소가 아니다.
int main(void){
	Add(14,20);
    Add(2.9, 2.3);//이렇게 하면 전달되는 인자의 자료형을 참조하여 호출될 함수의 유형을 컴파일러가 결정하기 때문이다.
}
  • 위와 같은 방식으로 호출해도 된다. 컴파일러가 전달 된 인자의 자료형을 참조하여 알아서 잘 맞는 함수는 호출해준다.

함수 템플릿과 템플릿 함수

  • 위에서 보인 정의를 가리켜 함수 템플릿이라 한다.
  • 반면, 위의 템플릿을 기반으로 컴파일러가 만들어 내는 다음 유형의 함수들을 가리켜 템플릿 함수라 한다.
int Add<int>(int num1, int num2)// 컴파일러가 컴파일시 함수 템플릿을 참조해서 만든 템플릿 '함수'
{
	return num1 + num2;
}
  • tip 1: 템플릿 함수는 컴파일러에 의해서 생성된 함수이기 때문에 생성된 함수(Generated Function)로도 불린다.
  • tip 2: 템플릿 함수와 일반 함수 중가 공존하는 코드에 일반 호출 Add(5,67)을 할 때, 일반 함수가 불리고, Add<in>(5,67)과 같이 템플릿 함수의 호출을 명시해야 템플릿 함수가 호출된다.
  • tip 3: 그러니까 함수 템플릿을 정의한 상황에서 일반함수까지 정의하는 것은 자제하자... 바람직하지 못하다.

둘 이상의 형(Type)에 대해 템플릿 선언하기

함수 템플릿을 만들때, 꼭 1개의 type만으로만 만들 수 있는 것은 아니다.

template <class T1, class T2>
void ShowData(double num){
	cout << (T1)num << ", " << (T2)num <<endl;
}

위와 같이 2개 이상의 타입도 가능하다.

함수 템플릿의 특수화(Specialization)

템플릿 함수의 구성방법에 예외를 둘 필요가 있는데, 이 떄 사용되는 것이 함수 템플릿의 특수화(specialization of gunction template이다.

template <class T>
T Max(T a, T b){
	return a> b? a:b;
}
int main(void){
	cout << Max(11, 15);
    cout << Max("Simple", "Best");
}

위와 같은 구문이 있을때, Max(11,15)는 문제없이 의도대로 작동하나, Max("Simple", "Best")는 실제 길이or사전순을 비교하는 것이 아니라, 단순히 주소 값의 비교경과를 반환되므로 의미가 없어진다.
이를 막기 위해 함수 템플릿의 특수화를 써서 해결해보자

template <class T>
T Max(T a, T b){
	return a> b? a:b;
}
template <>
char* Max(char *a, char* b){// char* Max<char*>요런 식으로 적으로 좀더 정보를 명확히 하는 방법이 된다.
	cout << "special max" <<endl;
    return strlen(a) > strlen(b) ? a: b;
}
template <>
const char* Max(char *a, char* b){
	cout << "special max" <<endl;
    return strcmp(a,b) > 0 ? a: b;
}
int main(void){
	cout << Max(11, 15);
    cout << Max("Simple", "Best");
}
  • 위의 template<>코드 아래 적힌 Max함수 들은 각각 char*, const char*형은 "내가 이렇게 제시를 하니, 그 타입의 템플릿 함수가 필요한 경우에는 별도로 만들지 말고 이것을 써라"라고 컴파일러에게 알려주는 것이다.

13-2. 클래스 템플릿 (Class Template)

클래스 템플릿의 정의

앞서 함수를 템플릿으로 정의했듯이 클래스도 템플릿으로 정의가 가능하다. 그리고 이렇게 정의된 템플릿을 가리켜 클래스 템플릿이라 하며, 이를 기반으로 컴파일러가 만들어 내는 클래스를 가리켜 템플릿 클래스라 한다.

template<class T>
class Point{
private:
	T xpos, ypos;
public:
	Point(T x=0, T y=0): xpos(x), ypos(y)
    {}
    void ShowPosition() const
    {
    	cout << '[' << xpos << ", " << ypos << ']' << endl;       
    }
};
  • 위와 같이 클래스 템플릿을 작성할 수 있다.

    함수 템플릿 기반과 다르게 클래스 템플릿 기반의 객체생성에는 반드시! 자료형 정보를 명시하도록 되어있다.

클래스 템플릿의 선언과 정의의 분리

클래스 템플릿도 멤버함수를 클래스 외부에 정의하는 것이 가능하다. 예를 들어,

template <class T>
class SimpleTemplate
{
	public:
    	T SimpleFunc(const T& ref);
};

이 템플릿의 멤버함수 SimpleFunc은 다음과 같이 외부에 정의해야 한다.

template <class T>
T SimpleTemplate<T>::SimpleFunc(const T& ref){} //여기서 T SimpleTemplate<T>는 
					//"T에 대해 템플릿화 된 simple Template 클래스 템플릿을 뜻한다."
  • 이때, template <class T>를 빼면 에러가 난다. T가 무엇인지 모르기 때문
profile
언제나 감사하며 살자!

0개의 댓글