일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 1인 게임 제작
- 1인 개발
- portal
- 게임 개발
- Pong
- 정처기 필기
- FPS
- Unity #Unity2D #Portal
- 퐁
- 자바스크립트
- Unity2D
- 필기
- 유니티3d
- 정보처리기사
- 게임
- 유니티 3D
- 프로그래머스 #최소힙 #우선순위 큐
- 1인 게임
- 토이 프로젝트
- 유니티
- unity3d
- 3회차
- 1인 게임 개발
- 게임 제작
- 게임제작
- 합격
- 정처기
- Unity
- Vampire Survivors
- 자바스크립트 게임
- Today
- Total
Coding Feature.
C++) Template. 본문
Template
템플릿(Template)이란 사용자가 템플릿 매개 변수에 대해 제공하는 인수를 기반으로 컴파일 시간에 일반 형식 또는 함수를 생성하는 구문이라고 한다.
즉 컴파일러가 컴파일 도중 사용자가 지정한 규칙(템플릿)을 기반으로 코드에 어떤 코드를 직접 써주는 것을 의미한다.
템플릿은 다음과 같은 상황에서 쓰이면 좋다.
void PrintSomething(int A){
std:: cout << A;
}
int main(){
PrintSomething(100); // 출력 '100'
PrintSomething("Print ME!"); // 에러
return 0;
}
위에서 인자에 어떤 값을 받고 그 값을 그대로 출력하는 함수 PrintSomething이 있다. 인자 type을 int로만 선언했기 때문에 "Print ME!" 와 같은 string type을 전달하려고 하면 에러가 뜬다.
위를 해결하기 위해서는 다음과 같이 코드를 추가로 작성할 수 있을 것이다.
void PrintSomething(int A){
std:: cout << A;
}
// ***추가***
void PrintSomething(std::string A){
std:: cout << A;
}
int main(){
PrintSomething(100); // 출력 '100'
PrintSomething("Print ME!"); // 에러
return 0;
}
함수와 인자의 이름은 모두 같지만 인자의 type만 다르게 해서 함수를 선언했는데 이는 C++ 언어가 함수 오버로딩(Function Overloading)을 지원하기 때문이다. 오버로딩이란 동일한 이름의 함수를 둘 이상 지정할 수 있는 것이다.
이렇게 인자의 타입을 따로 작성하는 방법도 충분히 사용가능하지만, 함수는 하나만 선언하고 인자를 건내주는데 그 타입은 컴파일러가 나중에 알아서 그에 맞게 넣어주도록 작성할수도 있다. 그게 바로 Template이다.
template <typename T>
void PrintSomething(T A){
std:: cout << A;
}
int main(){
PrintSomething(100);
PrintSomething("Print ME!");
PrintSomething(10.5);
PrintSomething('c');
return 0;
}
위와 같이 템플릿으로 type 이름을 T로 선언해주면 아래 main 함수에서 건내주는 인자 값들에 대해서 모두 정상적으로 출력이 되는 것을 확인할 수 있다.
만약 함수 인자로 전달하는 값의 타입을 명시하고 싶다면 다음과 같이 앞에 '<인자 타입>'을 붙이면 된다.
template <typename T>
void PrintSomething(T A){
std:: cout << A;
}
int main(){
PrintSomething<int>(100);
PrintSomething<std::string>("Print ME!");
PrintSomething<float>(10.5);
PrintSomething<char>('c');
return 0;
}
위와 같이 같은 기능을 하는 함수에 대해서 서로 다른 인자의 타입을 선언해줄 때 사용하는 Template을 함수 템플릿(Function Template)이라고 한다.
여기서 T는 템플릿 매개 변수이고, typename은 매개 변수의 형식을 의미한다.(typename은 형식의 자리 표시자임을 의미.)
원형은 다음과 같다.
template <typename 타입이름> // 보통 타입 이름으로 'T'를 사용.
function{
}
템플릿은 함수 뿐 만이 아니라 클래스를 생성할 때에도 적용이 가능하다.
template<typename T>
class SomeClass{
private:
T _N;
public:
SomeClass(T n) : _N(n){}
T GetN() const {return _N;}
};
int main(){
SomeClass someClassInt(5);
std:: cout << someClassInt.GetN();
SomeClass someClassFloat(9.8f);
std:: cout << someClassFloat.GetN();
SomeClass someClassString("Hello Template!");
std:: cout << someClassString.GetN();
return 0;
}
SomeClass라는 클래스의 private 변수의 타입을 T로 정의하고, 객체를 초기화할때 넘겨주는 값에 따라 타입이 달라지도록 할 수 있다.
위와 같이 클래스에 대해서 템플릿으로 정의하는 것을 클래스 템플릿(Class Template)이라고 한다.
클래스 템플릿을 사용해서 다음과 같은 유용한 일을 할 수 있다.
만약 어떤 클래스 내에서 멤버 변수로 정적 배열을 사용할 때, 이는 컴파일 타임에서 스택에 할당되기 때문에 미리 배열의 크기를 명시해야했다. 하지만 템플릿을 사용한다면 다음 코드와 같은 일이 가능해진다.
template<typename T, int N>
class SomeArray{
private:
T _array[N];
public:
int GetN() const {return N;}
};
int main(){
SomeArray<int, 6> someArray; // array의 타입명은 int, array의 사이즈는 6으로 초기화.
std:: cout << someArray.GetN();
return 0;
}
객체를 생성할 때 배열 안에 담길 값의 타입은 물론, 배열의 크기까지 명시해줌으로써 객체마다 다른 배열의 크기를 지정해 줄 수 있게 되었다. 이는 컴파일이 될 때 컴파일러가 템플릿 매개변수에 대해서 직접 그 값을 넣어주고 컴파일하기 때문이다.
실제로 컴파일할 때 위 코드는 다음과 같은 코드로 바뀌는 것과 같다. (단 클래스 객체를 생성할 때에만)
class SomeArray{
private:
int _array[6]; // T가 int로, N이 6으로 바뀜.
public:
int GetN() const {return 6;}
};
참고자료.
https://www.youtube.com/watch?v=I-hZkUa9mIs&t=292s
https://learn.microsoft.com/ko-kr/cpp/cpp/templates-cpp?view=msvc-170#type_parameters