728x90
템플릿 매개변수
- 일반적으로 클래스 템플릿을 작성할 때는 template <typename T> 처럼
꺽쇠괄호 안에 매개변수를 나열한다. - 이 매개 변수 T뿐만 아니라, 함수의 매개변수처럼 원하는 수 만큼 지정할 수 있다.
이때, 매개변수를 타입 대신 디폴트 값으로 정해도 된다.
template<typename T, int size> //템플릿의 타입을 2개로 m_array의 size를 받는다.
class ClassArr
{
private:
T m_array[size];
public:
T* getArray() { return m_array; }
T& operator[](int index)
{
return m_array[index];
}
void print()
{
for (int count = 0; count < size; ++count)
cout << (*this)[count] << ' ';
cout << '\n';
}
};
int main(void)
{
const int _size = 10;
ClassA<int, _size> sarr; //_size ClassA를 인스턴스화 할때 두번째 타입의 정수크기 만큼 배열을 할당한다.
for (int i = 0; i < 10; ++i)
{
sarr[i] = i + 1; //ClassA의 객체에 1~10까지 대입
}
sarr.print(); //1~10출력
return 0;
}
클래스 템플릿의 특수화
- 특정한 경우에 대해서만 템플릿을 다르게 구현하는 것을 템플릿 특수화라고 한다.
- ex)
형을 제외한 나머지 일반 타입<int,double,float,short..>들은 동일하게 처리하고 char형만 조금 다르게 처리하고 싶다.
- ex)
template<typename T>
class ClassA
{
public:
void print()
{
cout << "일반화 일반화" << '\n';
}
void test() {};
};
template<>
class ClassA<char> //Specialization
{
public:
void print()
{
cout << "char 특수화" << '\n';
}
};
int main(void)
{
ClassA<int> int_a;
ClassA<double> double_a;
ClassA<float> float_a;
int_a.print(); // "일반화 일반화" 출력
double_a.print(); // "일반화 일반화" 출력
float_a.print(); // "일반화 일반화" 출력
ClassA<char> char_a;
char_a.print(); // "char 특수화 출력
char_a.test() // Error 컴파일 에러 , 상속과 다른 개념이다.
// (서로 다른 클래스를 만들어서 동일한 이름으로 타입을 인슨터스화 시킬 수 있다고 생각해야함.)
return 0;
}
c++17에서 생성자로 클래스 템플릿 특수화 하기.
- 이 기능은 c++17 컴파일러에서 가능하다.
template<typename T>
class ClassA
{
public:
ClassA(const T& input){} // 생성자로 구분
void print()
{
cout << "일반화 일반화" << '\n';
}
void test() {};
};
template<>
class ClassA<char> //Specialization
{
public:
ClassA(const char& input) {}
void print()
{
cout << "char 특수화" << '\n';
}
};
int main(void)
{
ClassA int_a(10);
ClassA double_a(3.14);
ClassA float_a(2.5f);
int_a.print(); // "일반화 일반화" 출력
double_a.print(); // "일반화 일반화" 출력
float_a.print(); // "일반화 일반화" 출력
ClassA char_a('a');
char_a.print(); // "char 특수화 출력
return 0;
}
상속과 특수화 비교
- 템플릿 상속과 특수화의 차이점은 헷갈리기 쉽다.
구분 | 상속 | 특수화 |
---|---|---|
코드 재사용 | O : 파생 클래스는 베이스 클래스에 있는 데이터 멤버와 메서드를 모두 가진다. | X: 특수화를 할 때는 필요한 코드를 모두 다시 작성해야 한다. |
이름 재사용 | X : 파생 클래스의 이름은 반드시 베이스 클래스와 다르게 지어야한다. | O : 특수화 템플릿 클래스의 이름은 반드시 원본과 같아야 한다. |
다형성 지원 | O : 파생 클래스의 객체를 베이스 클래스의 객체로 표현할 수 있다. | X : 템플릿을 인스턴스화한 결과마다 타입이 다르다. |
- 구현을 확장하거나 다형성을 지원 -> 상속
- 특정한 타입에 대한 템플릿 구현을 커스터마이징 -> 특수화
템플릿을 메서드(함수)에 특수화 하기
template<typename T>
class ClassA
{
private:
T m_value;
public:
ClassA(const T& value) : m_value(value) {}
template<typename Q> //func를 호출하기위해 새로운 타입을 지정하고 호출해야함.
void func()
{
cout << "타입을 지정하고 호출한 함수" << '\n';
}
void doSomething() //타입 지정안하고 객체가 그냥 호출해도 되는 함수.
{
cout << "타입 없이 호출" << '\n';
}
};
int main(void)
{
ClassA<int> a(10);
//a.func(); //Error : func()를 호출하려면 a.func<int>() 이런식으로 타입을 정하고 호출 해야함!!
a.func<int>(); // "타입을 지정하고 호출한 함수" 출력
a.doSomething();// "타입 없이 호출" 출력
return 0;
}
300x250
'Programing_Language > C++' 카테고리의 다른 글
c++ 함수 포인터 (0) | 2020.12.16 |
---|---|
assert (단언하기) in C++ (0) | 2020.12.15 |
템플릿(Template) (1/2) (0) | 2020.12.13 |
2차원 동적 배열 할당과 해제 (배열 vs 벡터) (0) | 2020.12.07 |
enum과 enum class (열거 타입과 엄격한 열거 타입) (0) | 2020.12.06 |
댓글