본문 바로가기
C++/기초

C++ 기초 : 클래스 템플릿

글: 시플마 2024. 4. 17.

int형 데이터를 저장할 수 있는 가변 배열이 있습니다.

그런데 float형 데이터를 저장하는 가변 배열을 만들고자 한다면

클래스를 또 만들어야 하는 번거로움이 생깁니다.

 

또는 어떤 객체를 저장하는 가변 배열을 구성하고 싶을 수도 있죠.

 

결국 가변 배열 역할을 하는 클래스의 구성은

비슷하기 때문에 일일히 복사하여 클래스를 또 만들어야 

하고 다른 부분은 조금씩 수정하는 형태로 진행해야겠죠.

 

 

이러한 번거로움을 해소하기 위해서는

클래스도 템플릿으로 구성하면 됩니다.

 

가변 배열 클래스의 헤더 파일인

 

cArr.h로 가서 cArr 클래스를

템플릿으로 선언해 줍니다.

 

 

이후 main.cpp에서

 

cArr 클래스를 통해 객체를 만드려고 하면

오류가 발생합니다. 이제 일반 클래스가 아닌

클래스 템플릿이기 때문에 자료형을 써 주어야 합니다.

그럼 해당 자료형으로 클래스가 만들어질 것이고

이렇게 생성된 클래스를 통해 객체를 만들겠죠.

 

 

 


 

 

 

 

다시 cArr.h로 가서

 

cArr 클래스에서

필요한 부분은 T로 바꿨습니다.

 

먼저 멤버 m_pInt의 자료형을 T로 바꿨습니다.

 

가변 배열을 가리키는 m_pInt는

이제 가변 배열에 어떤 데이터가 있든지

가리킬 수 있어야 하기 때문이죠.

 

나머지 두 멤버는 가변 배열의 공간과 데이터 수를

나타내는 멤버이기 때문에 정수형이면 되겠죠?

 

 

그다음 데이터를 넣기 위한 함수,

push_back 함수를 보겠습니다.

 

어떤 데이터가 들어올지 모르기 때문에 

T로 바꿔야 합니다. 그런데 const와 &가 붙었습니다.

 

이유는 성능 때문입니다. 

 

그냥 T형의 데이터를 인자로 받으면

T형의 데이터가 복사된 후

push_back 함수의 매개변수(지역 변수)에

T형의 데이터가 저장되겠죠.

 

근데 만약 이 T형의 데이터가 일반적인 int나

float이 아닌 커다란 객체라고 생각해 봅시다.

 

용량이 큰 객체를 넣기 위해 이를 복사한 후에

가변 배열에 넣는 것은 비효율적입니다.

 

그래서 복사를 하지 않고 참조하여

값을 바로 가변 배열에 대입하기 위해

&를 붙입니다. 또한 참조한 데이터의

값은 참조해서 넣기만 해야 하지,

원본 값을 바꾸면 안되기 때문에 const를 붙여

원본 값을 수정하지 않겠다는 의미를 나타내 줍니다.

 

 

18번째 줄에 있는 함수의 매개변수는

인덱스에 접근하기 위한 변수이기 때문에

정수로 두어야 합니다. 반환 타입은 가변 배열에 있는

데이터가 무슨 형이든 값을 얻을 수 있도록 T로 바꾸어 줍니다.

 

 

다시 7번째 줄을 보면

멤버명이 m_pInt로 되어 있습니다.

 

원래 int형 데이터가 들어 있는 가변 배열의

주솟값을 저장하는 변수기 때문인데요, 

이제는 어떤 데이터가 들어 있든 해당 가변 배열을

가리킬 수 있어야 해서 T형으로 바꿨기 때문에

이름도 바꾸겠습니다.

 

멤버명을 클릭하고 Ctrl + R + R을 입력하면

 

아래와 같이 이름 바꾸기 창이 나오는데

m_pData로 바꾸고 미리 보기를 누른 후 적용하면

다른 파일에 있는 m_pInt도 m_pData로 바뀝니다.

(안되시면 템플릿 구문을 지우고 다시 실행해 보세요.)

 

 

 


 

 

 

헤더 파일과 소스 파일로 분리된 클래스를

클래스 템플릿으로 전환할 때 주의점이 있습니다.

 

클래스 템플릿은 클래스의 선언과 정의를

헤더 파일에 다 작성해야 한다는 점이죠.

 

 

main.cpp에서 클래스 템플릿을 통해 int형 객체를 만들었다고 합시다. 

 

그럼 컴파일러는

 

"음, 헤더 파일을 보니 클래스 템플릿이 있군.

int형으로 객체를 만들었으니

헤더 파일에 있는 클래스 템플릿을 통해

T 자리를 int로 대체하여 클래스를 만들면 되겠군."

 

위처럼 판단합니다.

 

하지만 헤더 파일에는 클래스 템플릿의 선언밖에 없죠?

그러므로 클래스의 선언 부분만 int로 대체하여 만들고

정의 부분은 그대로 T형으로 되어 있어 오류가 발생합니다.

 

 

이러한 이유로 클래스 템플릿은 클래스의 선언과 정의를 서로

다른 파일에 작성하면 안되고 헤더 파일에 모두 작성해야 하죠.

 

 

그래서 cArr.h에 

 

클래스 템플릿의 정의 부분도 작성을 해 주었는데

생성자와 소멸자, 다른 함수에도 모두 템플릿 구문을 붙여야 합니다.

또한 범위 지정 연산자(::) 앞에 붙은 클래스명에도 T형임을 

명시해야 하죠.

 

이유는 만약 cArr 클래스 템플릿을 통해 float형 객체를 만들면

T가 float으로 대체된 클래스가 만들어지겠죠.

이 상태에서 float형으로 구성된 cArr 클래스의 생성자,

float형으로 구성된 cArr 클래스의 소멸자,

float형으로 구성된 cArr 클래스의 함수에

제대로 접근할 수 있도록 명시해 주는 겁니다.

 

 

34번째 줄에서

동적 할당하는 부분도 T형으로 바꿔야 합니다.

 

가변 배열로 사용할 동적 할당 공간에 어떠한

자료형의 데이터든지 들어갈 수 있도록 하기 위해서죠.

 

 

resize 함수의

 

동적 할당 부분도 같은 이유로 T형으로 바꿔야겠죠?

 

 


 

 

 

실행 결과를 살펴 보죠.

 

cArr형 객체 carr을 생성했습니다.

float임을 명시했기 때문에 객체 carr은

float형 데이터가 들어간 가변 배열을 가리킬 수 있겠네요.

 

동적 할당된 가변 배열 공간에 1.1, 1233.1, 45.0을 넣습니다.

 

그리고 두 번째 공간의 값(1233.1)을 fData에 넣은 후

두 번째 공간에 99.99를 넣습니다.

 

그리고 두 번째 공간에 있는 값(99.99)을 fData2에 대입하고

로컬 창에서 확인해 보면 잘 작동한 것을 알 수 있습니다.

 

 

 

 

강의 출처 : https://www.youtube.com/watch?v=PFc4g8mxOiI&list=PL4SIC1d_ab-aOxWPucn31NHkQvNPHK1D1&pp=iAQB