C++ 초급 - 9. 템플릿 기초 (2 - 클래스 템플릿 (Class Template))

2025. 2. 22. 17:05프로그래밍 언어/C++

📌 9.2 클래스 템플릿 (Class Template)

C++의 클래스 템플릿(Class Template)데이터 타입에 의존하지 않는 범용적인 클래스를 만들 수 있도록 해준다.
이를 활용하면 코드 중복을 줄이고, 다양한 타입을 지원하는 재사용 가능한 클래스를 구현할 수 있다.
STL(Standard Template Library)의 vector, map, set 등의 컨테이너도 클래스 템플릿을 기반으로 설계되어 있다.


📌 1. 클래스 템플릿 기본 개념 (template<class T>)

🔹 (1) 클래스 템플릿이란?

  • 템플릿을 사용하면 데이터 타입에 의존하지 않는 범용적인 클래스를 정의할 수 있음.
  • template<class T> 또는 template<typename T>를 사용하여 선언.
  • 클래스 내부에서 T는 사용자가 지정한 타입으로 변경되어 컴파일됨.

💡 기본 문법

template<class T>  // T: 타입 매개변수
class 클래스이름 {
public:
    T 변수명;  // T 타입의 변수 선언
    void 함수이름(T 값);  // T 타입을 사용하는 함수 선언
};

💡 예제: 클래스 템플릿 기본 개념

#include <iostream>

// 클래스 템플릿 정의
template<class T>
class Box {
private:
    T value;
public:
    Box(T val) : value(val) {}
    void show() { std::cout << "저장된 값: " << value << std::endl; }
};

int main() {
    Box<int> intBox(100);       // int 타입 템플릿 사용
    Box<double> doubleBox(3.14); // double 타입 템플릿 사용
    Box<std::string> strBox("Hello"); // string 타입 템플릿 사용

    intBox.show();
    doubleBox.show();
    strBox.show();

    return 0;
}

🔹 출력 결과

저장된 값: 100
저장된 값: 3.14
저장된 값: Hello

💡 설명

  • template<class T>를 사용하여 데이터 타입을 일반화.
  • Box<int>, Box<double>, Box<std::string> 타입에 맞게 자동으로 클래스가 생성됨.

📌 2. 클래스 템플릿 선언 및 객체 생성 방법

🔹 (1) 클래스 템플릿 선언

  • 클래스 선언 시 template<class T>를 사용하여 타입을 일반화.

💡 기본 문법

template<class T>
class 클래스이름 {
public:
    T 변수;
    클래스이름(T v) : 변수(v) {}
};

🔹 (2) 객체 생성 방법

  • 템플릿 클래스를 사용할 때 타입을 명시해야 함.
클래스이름<int> 객체명(값);
클래스이름<double> 객체명(값);

💡 예제: 클래스 템플릿 객체 생성

Box<int> intBox(42);  // int 타입의 Box 객체 생성
Box<std::string> strBox("템플릿 클래스");  // string 타입의 Box 객체 생성

📌 3. 템플릿 멤버 함수의 정의 및 구현

🔹 (1) 템플릿 클래스의 멤버 함수 정의

  • 클래스 내부에서 정의하는 경우
template<class T>
class Example {
public:
    T data;
    Example(T val) : data(val) {}
    void show() { std::cout << "데이터: " << data << std::endl; }
};
  • 클래스 외부에서 정의하는 경우
template<class T>
class Example {
public:
    T data;
    Example(T val);
    void show();
};

// 멤버 함수 구현 (클래스 외부)
template<class T>
Example<T>::Example(T val) : data(val) {}

template<class T>
void Example<T>::show() {
    std::cout << "데이터: " << data << std::endl;
}

💡 예제: 클래스 외부에서 템플릿 멤버 함수 구현

#include <iostream>

template<class T>
class Calculator {
private:
    T num1, num2;
public:
    Calculator(T a, T b) : num1(a), num2(b) {}
    T add();
};

// 멤버 함수 구현
template<class T>
T Calculator<T>::add() {
    return num1 + num2;
}

int main() {
    Calculator<int> intCalc(10, 20);
    std::cout << "정수 덧셈 결과: " << intCalc.add() << std::endl;

    Calculator<double> doubleCalc(5.5, 2.3);
    std::cout << "실수 덧셈 결과: " << doubleCalc.add() << std::endl;

    return 0;
}

🔹 출력 결과

정수 덧셈 결과: 30
실수 덧셈 결과: 7.8

📌 4. 클래스 템플릿의 특수화 (Template Specialization)

🔹 (1) 특정 타입에 대해 다른 구현 제공

  • 템플릿을 특정 타입에 대해 맞춤 구현이 필요할 경우 특수화를 사용.

💡 예제: char* 타입에 대한 특수화

#include <iostream>

// 기본 템플릿
template<class T>
class Data {
public:
    static void show(T val) { std::cout << "값: " << val << std::endl; }
};

// 특수화 (char* 타입 전용)
template<>
class Data<char*> {
public:
    static void show(char* val) { std::cout << "문자열: " << val << std::endl; }
};

int main() {
    Data<int>::show(10);      // 일반 템플릿 사용
    Data<char*>::show("Hello"); // 특수화된 템플릿 사용

    return 0;
}

🔹 출력 결과

값: 10
문자열: Hello

💡 설명

  • char* 타입의 경우, 기본 템플릿이 아니라 특수화된 버전이 사용됨.

📌 5. 클래스 템플릿의 부분 특수화 (Partial Specialization)

🔹 (1) 일부 타입만 특수화 가능

  • 기본 템플릿 구조를 유지하면서 특정 부분만 특수화할 수 있음.

💡 예제: 부분 특수화

#include <iostream>

// 기본 템플릿
template<class T1, class T2>
class Pair {
public:
    T1 first;
    T2 second;
    Pair(T1 a, T2 b) : first(a), second(b) {}
    void show() { std::cout << "First: " << first << ", Second: " << second << std::endl; }
};

// 부분 특수화 (T2가 `int`일 때)
template<class T1>
class Pair<T1, int> {
public:
    T1 first;
    int second;
    Pair(T1 a, int b) : first(a), second(b) {}
    void show() { std::cout << "특수화된 버전 - First: " << first << ", Second(int): " << second << std::endl; }
};

int main() {
    Pair<std::string, double> p1("Hello", 3.14);
    p1.show();

    Pair<std::string, int> p2("World", 42); // 부분 특수화된 버전 호출
    p2.show();

    return 0;
}

🔹 출력 결과

First: Hello, Second: 3.14
특수화된 버전 - First: World, Second(int): 42

📌 6. 템플릿과 상속 (템플릿 기반 클래스 확장)

🔹 (1) 템플릿 클래스 상속

template<class T>
class Base {
public:
    T value;
    Base(T v) : value(v) {}
};

// 상속받은 클래스
template<class T>
class Derived : public Base<T> {
public:
    Derived(T v) : Base<T>(v) {}
};

📌 7. 정리

개념  설명
클래스 템플릿 기본 개념 template<class T>을 사용하여 범용 클래스 작성
템플릿 멤버 함수 클래스 외부에서 정의 가능
템플릿 특수화 특정 타입에 대해 다른 구현 제공
부분 특수화 일부 타입에 대해서만 특수화 가능
템플릿과 상속 템플릿 기반 클래스를 확장 가능