2022. 4. 2. 02:47ㆍC++
템플릿을 활용하여 c++에서 자료형을 마음대로 가지고 놀 수 있다.
구조체 -> 자료형을 사용자의 입맛대로 만드는 것. (구조체와 클래스는 거의 유사)
템플릿은 함수 템플릿과 클래스 템플릿으로 나눌 수 있다.
함수 템플릿
함수를 만들어 낼 때, 자료형을 정의하지 않고 두는 것.
c++에서는 오버로딩에 의해 아래와 같이 함수의 이름과 내용이 같은 코드가 성립한다.
int sum(int a, int b){
return a + b;
}
double sum(double a, double b){
return a + b;
}
이는 매우 귀찮은 일이다. 같은 내용이더라도 전달받는 인자의 자료형이 달라지면, 새로 함수를 정의해야 한다 .
하지만 template을 사용하게 되면 아래와 같이 하나의 함수만 정의하면 된다
template <typename T> //typename 대신 class를 사용해도 된다.
T sum(T a, T b){
return a + b;
}
만약 인자들의 자료형이 다를 경우엔 아래와 같다.
template <typename T1, typename T2> //typename 대신 class를 사용해도 된다.
void printAll(T1 a, T2 b){
cout << "T1: " << a <<endl;
cout << "T2: " << b <<endl;
}
template 함수 예시 1.
#include <iostream>
#include <string>
using namespace std;
template <typename T> //typename 대신 class를 사용해도 된다.
T sum(T a, T b){
return a + b;
}
int main(void){
cout<<"int sum: ";
cout<< sum<int>(3,4)<<endl;
cout<< sum(3,4)<<endl; // 템플릿 함수를 사용할 때, 어떤 자료형을 쓰는지 명확하게 표시하는 것이 좋다.
cout<<"string sum: ";
cout<< sum<string>("hello","world")<<endl;
// cout<< sum("hello", "world"); 오류 발생. error: invalid operands of types 'const char*' and 'const char*' to binary 'operator+'
return 0;
}
template 함수 예시 2.
#include <iostream>
#include <string>
using namespace std;
template <typename T1, typename T2> //typename 대신 class를 사용해도 된다.
void printAll(T1 a, T2 b){
cout << "T1: " << a <<endl;
cout << "T2: " << b <<endl;
}
int main(void){
printAll<string, int>("hello", 13);
printAll("hello", 13);
return 0;
}
예시 1에서 자료형을 명확하게 표시하지 않았더니 오류가 발생했다.
이는 컴퓨터가 "hello"와 "world"를 string 자료형이 아닌 const char*로 해석하였기 때문이다.
Tip. C에서는 문자열의 반환값이 char지만, C++에서는 const char이다. 즉 아래의 코드는 에러를 발생시킨다.
#inclue<iostream>
using namespace std;
void printAll(char* str){ //오류발생. char을 const char으로 바꿔줘야 한다.
cout<<str<<endl;
}
int main(void)
{
printAll("hello");
return 0;
}
템플릿 특수화
템플릿을 사용할때, 특수한 자료형에 대해서는 다른 처리를 하고 싶을 때 사용한다.
사용법은 아래와 같다.
template <typename T> //typename 대신 class를 사용해도 된다.
T sum(T a, T b){
return a + b;
}
template<>
char * sum<char*> (char* s1, char* s2){
char * str= "[char *]문자열은 더할 수 없습니다.";
return str;
}
클래스 템플릿
클래스 내부의 멤버 변수의 타입에 대하여 template으로 선언할때 사용한다.
유의할 점: 멤버 함수 클래스 외부에서 선언 할 때, 꼭 template 선언을 다시 해주어야 한다.
클래스 템플릿은 객체를 생성할 때 타입을 정해준다.
1. 멤버함수가 클래스 내에 선언되었을때
#include <iostream>
#include <string>
using namespace std;
template <typename T>
class Person{
private:
string name;
T height;
public:
Person(string name, T height):name(name), height(height){}
void printAll(){
cout << "name : " << name << endl;
cout << "number : " << height << endl;
};
void setName(string name){
this->name = name; //this->name은 멤버변수를 가르킨다. name은 멤버함수내의 매개변수를 가르킨다.
}
void setNumber(T height){
this->height = height;
}
};
int main() {
//객체를 선언할때 <> 안에 template 의 타입을 넣는다.
Person<int> p1("Mr. Dev C++", 173);
Person<string> p2("Ms. Unix", "155cm");
p1.printAll();
p2.printAll();
cout << endl;
p1.setNumber(188);
p2.setNumber("2m 10cm");
cout << endl;
p1.printAll();
p2.printAll();
return 0;
}
2. 멤버함수가 클래스 밖에 선언되었을 때
> 외부에 선언하는 멤버 함수 및 생성자 마다 template선언을 해주어야 한다.
#include <iostream>
#include <string>
using namespace std;
template <typename T>
class Person{
private:
string name;
T height;
public:
Person(string name, T height);
void printAll();
void setName(string name);
void setNumber(T height);
};
template <typename T>
Person<T>::Person(string name, T height):name(name), height(height){}
template <typename T>
void Person<T>::printAll(){
cout << "name : " << name << endl;
cout << "number : " << height << endl;
};
template <typename T>
void Person<T>::setName(string name){
this->name = name;
}
template <typename T>
void Person<T>::setNumber(T height){
this->height = height;
}
int main() {
//main 함수는 동일하다.
Person<int> p1("Mr. Dev C++", 173);
Person<string> p2("Ms. Unix", "155cm");
p1.printAll();
p2.printAll();
cout << endl;
p1.setNumber(188);
p2.setNumber("2m 10cm");
cout << endl;
p1.printAll();
p2.printAll();
return 0;
}
출처: https://blockdmask.tistory.com/45 [개발자 지망생]
'C++' 카테고리의 다른 글
new와 delete (0) | 2022.04.03 |
---|---|
malloc & free (0) | 2022.04.03 |
Reference (0) | 2022.04.03 |
call-by-reference & call-by-value (0) | 2022.04.02 |
pointer (0) | 2022.04.02 |