티스토리 뷰

프로그래밍/C++

클래스 템플릿

에어버스 2018. 6. 10. 12:55

클래스 템플릿 (함수템플릿 참고 : http://petra.tistory.com/1224

클래스를 만들어 내는 틀 (메태코드) 로 함수 템플릿과 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include "stdafx.h"
#include <iostream>
using namespace std;
 
class Array {
    int* buf, size, capacity;
public:
    explicit Array(int cap = 100) : buf(0), size(0), capacity(cap) { buf = new int[capacity]; }
    ~Array() { delete[] buf; }
    void Add(int data) { buf[size++= data; }
    int operator[](int idx) { return buf[idx]; }
    int GetSize() const { return size; }
};
int main()
{
    Array arr;
    arr.Add(10);
    arr.Add(20);
    arr.Add(30);
    for (int i = 0; i < arr.GetSize(); i++)
        cout << arr[i] << endl;
    _gettch();
    return 0;
}
cs

<실행>

위 코드는 정수형 배열만 취급하므로 실수와 문자열을 다루는 배열도 추가해봅니다.

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include "stdafx.h"
#include <iostream>
#include <string> // 문자열 취급
using namespace std;
 
class Array {
    int* buf, size, capacity;
public:
    explicit Array(int cap = 100) : buf(0), size(0), capacity(cap) { buf = new int[capacity]; }
    ~Array() { delete[] buf; }
    void Add(int data) { buf[size++= data; }
    int operator[](int idx) { return buf[idx]; }
    int GetSize() const { return size; }
};
class DoubleArray {
    double* buf;
    int size, capacity;
public:
    explicit DoubleArray(int cap = 100) : buf(0), size(0), capacity(cap) { buf = new double[capacity]; }
    ~DoubleArray() { delete[] buf; }
    void Add(double data) { buf[size++= data; }
    double operator[](int idx) { return buf[idx]; }
    int GetSize() const { return size; }
};
class StringArray {
    string* buf;
    int size, capacity;
public:
    explicit StringArray(int cap = 100) : buf(0), size(0), capacity(cap) { buf = new string[capacity]; }
    ~StringArray() { delete[] buf; }
    void Add(string data) { buf[size++= data; }
    string operator[](int idx) { return buf[idx]; }
    int GetSize() const { return size; }
};
int main()
{
    Array arr;
    arr.Add(10);
    arr.Add(20);
    arr.Add(30);
    for (int i = 0; i < arr.GetSize(); i++)
        cout << arr[i] << endl;
    cout << endl;
    DoubleArray darr;
    darr.Add(10.1);
    darr.Add(20.2);
    darr.Add(30.3);
    for (int i = 0; i < darr.GetSize(); i++)
        cout << darr[i] << endl;
    cout << endl;
    StringArray sarr;
    sarr.Add("abc");
    sarr.Add("ABC");
    sarr.Add("Hello");
    for (int i = 0; i < sarr.GetSize(); i++)
        cout << sarr[i] << endl;
    _gettch();
    return 0;
}
cs

<실행>

15~34행 까지 코드가 추가되어 Array 클래스가해야 할 일(인터페이스, 기능)은 같고 자료형만 다릅니다.

클라이언트 즉, main() 에서 배열 원소의 자료형을 결정할 수 없고 클래스에서 만들어진 자료형만 사용해야 하는 단점이 있습니다.

단점을 해결하기 위해 클래스 템플릿을 정의하는 것이다.
클래스 템플릿은 클래스를 정의하기 위한 메타 클래스 코드이며, 텤플릿 매개변수 인자를 통해 클라이언트가(main()) 클래스에 사용될 타입을 결정할 수 있게 된다.

클래스 템플릿은 클래스 앞에 template<T> 키워드를 붙이고, 클라이언트(main())가 매개변수 타입을 결정하게 타입을 일반화(T 타입)하면 된다.

클래스 템플릿 형식은 template<typename T> class Array 이다.

위 코드에서 15~34행 코드를 제거하고 template<typename T> 추가와 각 자료형을 T타입으로 바꾸면 아래와 같이 간단한 코드로 구현이 가능하다.

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
32
33
34
35
36
37
38
39
40
41
#include "stdafx.h"
#include <iostream>
#include <string> // 문자열 취급
using namespace std;
 
template <typename T>
class Array {
    T* buf;
    int size, capacity;
public:
    explicit Array(int cap = 100) : buf(0), size(0), capacity(cap) { buf = new T[capacity]; }
    ~Array() { delete[] buf; }
    void Add(T data) { buf[size++= data; }
    T operator[](int idx) { return buf[idx]; }
    int GetSize() const { return size; }
};
int main()
{
    Array<int> arr; // Array arr; 처럼 암시적 호출하면 배열 원소의 자료형을 결정하지 못해 에러난다.
    arr.Add(10);
    arr.Add(20);
    arr.Add(30);
    for (int i = 0; i < arr.GetSize(); i++)
        cout << arr[i] << endl;
    cout << endl;
    Array<double> darr;
    darr.Add(10.1);
    darr.Add(20.2);
    darr.Add(30.3);
    for (int i = 0; i < darr.GetSize(); i++)
        cout << darr[i] << endl;
    cout << endl;
    Array<string> sarr;
    sarr.Add("abc");
    sarr.Add("ABC");
    sarr.Add("Hello");
    for (int i = 0; i < sarr.GetSize(); i++)
        cout << sarr[i] << endl;
    _gettch();
    return 0;
}
cs

<실행>

클래스 템플릿은 클래스의 메타 코들일뿐이며 컴파일러는 클래스 템플릿(클래스 메타코드)를 이용해 실제 클래스(클래스 정의 코드)를 아래와 같이 만든다.

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
class Array<int> {
    int* buf;
    int size, capacity;
public:
    explicit Array(int cap = 100) : buf(0), size(0), capacity(cap) { buf = new int[capacity]; }
    ~Array() { delete[] buf; }
    void Add(int data) { buf[size++= data; }
    int operator[](int idx) { return buf[idx]; }
    int GetSize() const { return size; }
};
class Array <double>{
    double* buf;
    int size, capacity;
public:
    explicit Array(int cap = 100) : buf(0), size(0), capacity(cap) { buf = new double[capacity]; }
    ~Array() { delete[] buf; }
    void Add(double data) { buf[size++= data; }
    double operator[](int idx) { return buf[idx]; }
    int GetSize() const { return size; }
};
class Array <string>{
    string* buf;
    int size, capacity;
public:
    explicit Array(int cap = 100) : buf(0), size(0), capacity(cap) { buf = new string[capacity]; }
    ~Array() { delete[] buf; }
    void Add(string data) { buf[size++= data; }
    string operator[](int idx) { return buf[idx]; }
    int GetSize() const { return size; }
};
cs

템플릿 매개변수도 함수의 매개변수처럼 기본 매개변수 값을 지정할 수 있다.

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
32
33
34
35
36
37
38
39
40
41
#include "stdafx.h"
#include <iostream>
#include <string> // 문자열 취급
using namespace std;
 
template <typename T=intint capT=100>
class Array {
    T* buf;
    int size, capacity;
public:
    explicit Array(int cap = capT) : buf(0), size(0), capacity(cap) { buf = new T[capacity]; }
    ~Array() { delete[] buf; }
    void Add(T data) { buf[size++= data; }
    T operator[](int idx) { return buf[idx]; }
    int GetSize() const { return size; }
};
int main()
{
    Array<> arr; // 기본 매개변수 값 int, 100 사용 
    arr.Add(10);
    arr.Add(20);
    arr.Add(30);
    for (int i = 0; i < arr.GetSize(); i++)
        cout << arr[i] << endl;
    cout << endl;
    Array<double> darr; // 기본 매개변수 값 100 사용
    darr.Add(10.1);
    darr.Add(20.2);
    darr.Add(30.3);
    for (int i = 0; i < darr.GetSize(); i++)
        cout << darr[i] << endl;
    cout << endl;
    Array<string10> sarr; // 기본 매개변수 값 사용되지 않는다
    sarr.Add("abc");
    sarr.Add("ABC");
    sarr.Add("Hello");
    for (int i = 0; i < sarr.GetSize(); i++)
        cout << sarr[i] << endl;
    _gettch();
    return 0;
}
cs

<실행>

(클래스 템플릿 특수화)

클래스 템플릿도 특수화가 가능하며, 일반 버전의 템플릿을 사용할 수 없는 경우, 성능 개선이나 특수 기능을 위해 특수화 버전을 별도로 제공하고자 할때 사용한다.

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
#include "stdafx.h"
#include <iostream>
#include <string> // 문자열 취급
using namespace std;
 
template <typename T>
class ObjectInfo {
    T data;
public:
    ObjectInfo(const T& d) : data(d) {}
    void Print() {
        cout << "타입 : " << typeid(data).name() << endl;
        cout << "크기 : " << sizeof(data) << endl;
        cout << "값 : " << data << endl;
        cout << endl;
    }
};
int main()
{
    ObjectInfo<int> d1(10);
    d1.Print();
    ObjectInfo<double>d2(5.5);
    d2.Print();
    ObjectInfo<string>d3("Hello");
    d3.Print();
    _gettch();
    return 0;
}
cs

<실행>

실행 결과를 보면 문자열 "Hello" 길이가 5 이지만 크기가 28로 나오므로 T를 string으로 특수화 코드(18~31행)를 추가합니다.

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
32
33
34
35
36
37
38
39
40
41
42
#include "stdafx.h"
#include <iostream>
#include <string> // 문자열 취급
using namespace std;
 
template <typename T>
class ObjectInfo {
    T data;
public:
    ObjectInfo(const T& d) : data(d) {}
    void Print() {
        cout << "타입 : " << typeid(data).name() << endl;
        cout << "크기 : " << sizeof(data) << endl;
        cout << "값 : " << data << endl;
        cout << endl;
    }
};
template<>
class ObjectInfo<string>
{
    string data;
public:
    ObjectInfo(const string& d) : data(d) {}
    void Print() {
        cout << "타입 : string" << endl;
        cout << "크기 : " << sizeof(data) << endl;
        cout << "문자열 길이 : " << data.size() << endl;
        cout << "값 : " << data << endl;
        cout << endl;
    }
};
int main()
{
    ObjectInfo<int> d1(10);
    d1.Print();
    ObjectInfo<double>d2(5.5);
    d2.Print();
    ObjectInfo<string>d3("Hello");
    d3.Print();
    _gettch();
    return 0;
}
cs

<실행>

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/04   »
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