2023.01.20
전 티스토리에 썼던 거 옮기기
#윤성우의 열혈 c++ 프로그래밍 ch 13-2 (p.540~553)
01. 기본 예제
#include <iostream>
using namespace std;
template <typename T>
class Point
{
private:
T xpos, ypos;
public:
Point(T x=0, T y=0):xpos(x), ypos(y){} //생성자 이니셜라이저로 초기화
void ShowPos() const ///상태 출력 함수(변경x)
{
cout << '[' << xpos << ", " << ypos << ']' << endl;
}
};
int main()
{
Point<int> pos1(3, 4); //템플릿 클래스
pos1.ShowPos();
Point<double> pos2(2.4, 3.6); //템플릿 클래스
pos2.ShowPos();
Point<char> pos3('p', 'f'); //템플릿 클래스
pos3.ShowPos();
return 0;
}
→ 클래스 탬플릿 기반의 객체생성에는 반드시 자료형 정보 명시하기!!! (함수 템플릿에서는 생략 가능)
02, 클래스 탬플릿의 선언과 정의 분리 시키기
- 멤버 함수를 클래스 외부에 정의해보기~!~!!
#include <iostream>
using namespace std;
template <typename T>
class Point
{
private:
T xpos, ypos;
public:
Point(T x = 0, T y = 0); //생성자(매개변수의 디폴트 값은 클래스 템플릿 내에만 표시)
void ShowPos() const; ///상태 출력 함수(변경x)
};
template <typename T> //외부 정의할때마다 써주기!
Point<T>::Point(T x, T y): xpos(x), ypos(y){} //생성자 외부 정의시 외부에만 이니셜라이저!
template <typename T>
void Point<T>::ShowPos() const
{
cout << '[' << xpos << ", " << ypos << ']' << endl;
}
int main()
{
Point<int> pos1(3, 4); //템플릿 클래스
pos1.ShowPos();
Point<double> pos2(2.4, 3.6); //템플릿 클래스
pos2.ShowPos();
Point<char> pos3('p', 'f'); //템플릿 클래스
pos3.ShowPos();
return 0;
}
이걸 이용해서 파일까지 완벽 분리 시켜버리기
/* test0527.h */
#ifndef __POINT_TEMPLATE_H_
#define __POINT_TEMPLATE_H_
template <typename T>
class Point
{
private:
T xpos, ypos;
public:
Point(T x = 0, T y = 0); //생성자(매개변수의 디폴트 값은 클래스 템플릿 내에만 표시)
void ShowPos() const; ///상태 출력 함수(변경x)
};
#endif
/* test0527.cpp */
#include <iostream>
#include "test0527.h"
using namespace std;
template <typename T> //외부 정의할때마다 써주기!
Point<T>::Point(T x, T y): xpos(x), ypos(y){} //생성자 외부 정의시 외부에만 이니셜라이저!
template <typename T>
void Point<T>::ShowPos() const
{
cout << '[' << xpos << ", " << ypos << ']' << endl;
}
/* test0527_main */
#include <iostream>
#include "test0527.h"
#include "test0527.cpp" //소스파일까지 안 불러오면 컴파일 에러남!!
using namespace std;
int main()
{
Point<int> pos1(3, 4); //템플릿 클래스
pos1.ShowPos();
Point<double> pos2(2.4, 3.6); //템플릿 클래스
pos2.ShowPos();
Point<char> pos3('p', 'f'); //템플릿 클래스
pos3.ShowPos();
return 0;
}
main파일을 작성할 때 헤더파일뿐만 아니라 클래스 템플릿이 정의되어 있는 파일까지 같이 불러와줘야 됨!!
이유,,, 동시에 컴파일되긴 하는데 서로 다른 소스파일이라 서로 내용을 참조하지 않음~~~~~!!!
그래서
1. 헤더파일에 템플릿의 생성자와 멤버함수의 정의를 모두 넣거나
2. 위에 처럼 그냥 소스파일까지 같이 불러오거나
하면 됨
03. 배열 클래스의 템플릿화
/* ArrayTemplate.h */
#ifndef __ARRAY_TEMPLATE_H_
#define __ARRAY_TEMPLATE_H_
#include <iostream>
#include <cstdlib>
using namespace std;
template <typename T>
class BoundCheckArray
{
private:
T* arr; //템플릿 배열
int arrlen;
BoundCheckArray(const BoundCheckArray& arr) {} //생성자
BoundCheckArray& operator=(const BoundCheckArray& arr) {} //대입연산자
public: //멤버 함수 선언
BoundCheckArray(int len);
T& operator[] (int idx);
T operator[] (int idx) const;
int GetArrLen() const;
~BoundCheckArray(); //소멸자
};
/* 멤버 함수 정의
템플릿 형식 먼저 적어주고
반환형 -> 클래스 템플릿 타입 -> :: -> 함수 이름 -> (매개변수) -> 그 외 이니셜라이저나 const 등 */
template <typename T>
BoundCheckArray<T>::BoundCheckArray(int len) : arrlen(len)
{
arr = new T[len]; //동적할당
}
template <typename T>
T& BoundCheckArray<T>::operator[] (int idx)
{
if (idx < 0 || idx >= arrlen)
{
cout << "오류: 배열 범위 밖에 있음" << endl;
exit(1);
}
return arr[idx];
}
template <typename T>
T BoundCheckArray<T>::operator[] (int idx) const
{
if (idx < 0 || idx >= arrlen)
{
cout << "오류: 배열 범위 밖에 있음" << endl;
exit(1);
}
return arr[idx];
}
template <typename T>
int BoundCheckArray<T>::GetArrLen() const
{
return arrlen;
}
template <typename T>
BoundCheckArray<T>::~BoundCheckArray()
{
delete[]arr;
}
#endif
/* Point.h */
#ifndef __POINT_H_
#define __POINT_H_
#include <iostream>
using namespace std;
class Point
{
private:
int xpos, ypos;
public:
Point(int x = 0, int y = 0); //생성자 외부 정의 예정
friend ostream& operator<<(ostream& os, const Point& pos);
};
#endif
/* Point.cpp */
#include <iostream>
#include "Point.h"
using namespace std;
Point::Point(int x, int y) : xpos(x), ypos(y) {} //생성자 외부 정의
ostream& operator<<(ostream& os, const Point& pos) //멤버함수 외부 정의
{
os << '[' << pos.xpos << ", " << pos.ypos << ']' << endl;
return os;
}
/* ArrayMain.cpp */
#include <iostream>
#include "ArrayTemplate.h"
#include "Point.h"
using namespace std;
int main()
{
cout << "int형 정수 저장" << endl;
BoundCheckArray<int> iarr(5);
for (int i = 0; i < 5; i++)
iarr[i] = (i + 1) * 11;
for (int i = 0; i < 5; i++)
cout << iarr[i] << endl;
cout << endl;
cout<<"Point형 객체 저장"<<endl;
BoundCheckArray<Point> oarr(3);
oarr[0] = Point(3, 4);
oarr[1] = Point(5, 6);
oarr[2] = Point(7, 8);
for (int i = 0; i < oarr.GetArrLen(); i++)
cout << oarr[i];
cout << endl;
cout << "Point 객체의 주소 값 저장" << endl;
typedef Point* POINT_PTR;
BoundCheckArray<POINT_PTR> parr(3);
parr[0] = new Point(3, 4);
parr[1] = new Point(5, 6);
parr[2] = new Point(7, 8);
for (int i = 0; i < parr.GetArrLen(); i++)
cout << *(parr[i]);
delete parr[0];
delete parr[1];
delete parr[2];
return 0;
}
04. 문제 풀이
문제 1
인자로 전달되는 두 변수에 저장된 값을 서로 교환하는 SwapData라는 이름의 함수를 템플릿으로 정의해 보자. 그리고 다음 Point 클래스를 대상으로 값의 교환이 이뤄짐을 확인할 수 있도록 main함수를 구성해 보자.
/* 문제 13-1 :: 1번 */
#include <iostream>
using namespace std;
class Point
{
private:
int xpos, ypos;
public:
Point(int x=0, int y=0) : xpos(x), ypos(y){}
void Showpos() const
{
cout << '[' << xpos << ", " << ypos << ']' << endl;
}
};
template <typename T>
void SwapData(T& data1, T& data2) //참조를 이용하여 바꾸기
{
T temp = data1;
data1 = data2;
data2 = temp;
}
int main()
{
Point pos1(3, 4);
Point pos2(10, 20);
SwapData(pos1, pos2);
pos1.Showpos();
pos2.Showpos();
return 0;
}
문제 2
int형 배열에 저장된 값을 모두 더해서 그 결과를 반환하는 기능의 함수인 SumArray를 템플릿으로 정의하여, 다양한 자료형의 배열을 대상으로 합을 계산하는 예제를 작성해 보자.
/* 문제 13-1 :: 2번 */
#include <iostream>
using namespace std;
template <typename T>
T SumArray(T arr[], int len)
{
T sum = 0;
for (int i = 0; i < len; i++)
sum += arr[i];
return sum;
}
int main()
{
int arr1[] = { 10, 20, 30 };
cout << SumArray(arr1, sizeof(arr1) / sizeof(int)) << endl;
double arr2[] = { 10.3, 20.4, 30.5 };
cout << SumArray(arr1, sizeof(arr2) / sizeof(double)) << endl;
return 0;
}
'✨언어 > c++' 카테고리의 다른 글
[ch 14] 템플릿 2 (0) | 2024.06.25 |
---|