unreal 5기

250826 언리얼엔진 본캠프 16일차 템플릿

parkjinnam 2025. 8. 26. 12:03

템플릿

템플릿 문법은 다양한 자료형에 유연하게 대응하는 일반화된 코드를 작성할 수 있게한다. 프로그래밍에서는 정수형끼리의 연산과 실수형끼리의 연산이 서로 다르게 처리된다.(자료형 float나 double 등) 템플릿 문법을 활용하는 이러한 상황에 유연하게 처리하는 것이 가능하다.

 

함수 오버로딩

템플릿을 공부하기 전에 함수 오버로딩에 대해서 공부해야한다. C언어에서는 함수를 구별하는 요소는 함수의 이름이다. 즉 함수 이름이 같다면 같은 함수로 취급한다. 반면에 C++에서는 반환타입, 이름, 인자 3요소를 이용하여 고유한 이름을 작성하고 그 이름을 통해서 함수를 구별한다. 이름이 같아도 반환타입이나 받는 인자가 다르다면 다른 함수로 인식하는 것이다. 이를 네임 맹글링이라고 하며 동일한 이름의 함수를 여러 개 정의하는 것을 함수 오버로딩이라고 한다. 단 함수 오버로딩이 되기 위해서는 이름이 같더라도 각 함수가 명확하게 구분되어야한다. 또한 반환형만으로는 오버로딩이 성립하지 않는다. 그럼 어떻게 해야하는데? 같이 오버로딩이 유효한 조건을 살펴보도록 하자

 

1. 매개변수 타입이 다른 경우

#include <iostream>

using namespace std;

void print(int a)		//매개변수가 int자료형
{
	cout << a << endl;
}

void print(double a)		//매개변수가 double자료형
{
	cout << a << endl;
}

int main(void)
{
	print(10);
    print(3.14);
	return 0;
}

 

 

2. 매개변수의 개수가 다른 경우

#include <iostream>

using namespace std;

void print(int a, intb)
{
return a+b;
}

void print(int a, int b, int c)
{
return a+b+c;
}

int main(void)
{
cout << print(3, 4) << endl;
cout << print(1, 2, 3) << endl;
return 0;
}

 

여기서 주의해야할 점은 매개변수의 자료형이 다르더라도 둘다 적용 가능한 변수를 인자로 받는다면 애매모호한 함수 오버로딩으로 에러가 발생한다. 예컨데 10을 생각해보자 10은 int자료형으로도 10 double 자료형으로도 10.0으로서 같은 값을 갖고 이를 가지고 오버로딩을 시도하면 에러가 발생한다 위의 코드에 대입해서 확인해보자.

 

그렇다면 함수 오버로딩을하면 어떤 함수가 선택될까? 컴파일러는 최대한 변환할 수 있는 함수를 찾으려고 한다. C++에서는

정확한 매칭 > 타입 승격 변환 > 표준 타입 변환 >  사용자 정의 타입 변환의 순서로 호출할 함수를 결정한다.

 

1. 정확한 매칭 : 정확한 자료형으로의 매칭이 가능한지 

 

2. 타입 승격 변환 : 값이 손실되지 않는 방향으로 변환 즉 승격이 가능한지

 

3. 표준 타입 변환 : 값의 손실이 발생하더라도  변환이 가능한지(ex : int > double)

 

4.  사용자 정의 타입 변환 : 클래스 타입의 변환 함수나 생성자 등을 통해 이루어지는 변환.(심화 내용)

 

템플릿

 

Template은 타입에 관계없이 일반화된 코드를 작성하기 위한 문법으로서 문법 자체는 비교적 간단하다.

template < typename T>		//템플릿을 이용한 일반화된 함수를 정의

 

어떤 타입이 올지 모르겠으나 그 타입을 T라고 부르겠다 라는 의미로서 일반화하려는 타입 자리에 실제 타입 대신 T를 사용하면 된다.

template <typename T>
T add(T.a, T.b)		// 템플릿을 이용한 더하기 함수
{
return a+b;
}

 

 

템플릿 클래스

 

함수뿐만이 아니라 클래스도 템플릿으로 사용해 일반화 할 수 있다. 예컨데 배열에 원소를 추가하고 삭제하는 기능을 가진 클래스를 정의할 때도 템플릿을 사용하여 다양한 타입의 데이터에 대해 동작하도록 일반화 할 수 있다. 한번 실제로 만들어보자

 

1. 내부에 최대 100개 원소를 저장할 수 있는 배열과 원소 개수를 나타내는 변수를 갖는다.

2. 생성자에서 초기 원소 개수는 0으로한다.

3. add() 매서드를 구현한다. 인자를 받고 원소를 배열 맨 끝에 추가하며 100개를 초과하면 더 이상 원소를 받지 않는다.

4. remove() 매서드를 구현한다. 현재 저장된 원소가 1개 이상이면 마지막 원소를 제거한다.

5. print() 매서드를 구현한다. 현재 저장된 모든 원소를 출력한다.

 

#include <iostream>
using namespace std;

template <typename T>
class Array
{
	T data[100];
	int size;
public:
	Array() : size(0) {}
    
    void add(const T& element)
    {
    	if(size < 100)
        {
        	data[size++] = element;
        }
    }
    
    void remove()
    {
    	if(size >0)
        size--;
    }
    
    void print()
    {
    	for(int i = 0; i< size; i++)
        {
        	cout << data[i] << " ";
            cout << endl;
        }
    }
};

int main()
{
	Array<int> arr;		// 템플릿 클래스는 선언할때 자료형을 명시한다.
    arr.add(10);
    arr.add(20);
    arr.add(30);
    arr.print();
    arr.remove();
    arr.print();
    
    return;
}