본문 바로가기
  • hazard_dev@__
  • hazard_dev@__
C++

[C++]C++의 제네릭, Template class에 대해서

by Hazard3_o00sung 2021. 2. 17.
728x90

강력한 언어,C++입니다

Powerful Language C++ 

  프로그래밍 언어에는 다양한 타입들이 존재합니다. 하지만 프로그램 내부에서 동작되는 코드들의 타입은 들어가는 함수 별로 다를 수 있고, 또한 클래스에서는 더욱 다양한 타입들을 인자로 받을 수 있습니다. 만약 아래와 같이 코드가 작성되었다는 상황을 가정한다면,..

 

class Int
{
private:
	int myVar;
public:
	Int(int c),myVar(c){}
    ...
 };

 

위와 같은 Int클래스의 멤버 변수 중 하나인 myVar는 정수형 타입으로 선언된 멤버 변수이기도 하며, 클래스 생성자가 구현된 코드를 보게 되면, 당연하게도 정수형 타입의 인자를 매개 변수로 받아서 초기화 멤버 변수의 값이 초기화됩니다. 만약 위와 같은 코드가 정말 정수형 변수만 받는 다면, 클래스의 역할 또한 그것에만 국한된다라고 한다면, 아무 문제가 없습니다. 하지만 아래처럼 코드가 작성되어 있다고 가정해 봅시다.

 

class Int{};

class Float{};

class Double{};

class Unsigned{};
...

 

타입 별로 동작해야하는 수행 동작은 같으나, 타입이 다르다는 이유만으로 벌써 3개의 클래스가 추가되었다는 것을 확인할 수 있습니다. 과연 좋은걸 까요?

 

위와 같은 문제는 객체 지향 프로그래밍 언어라는 점을 고려하지 않은 디자인이라고 볼 수 있습니다. 그렇다면 어떻게 하면 위와 같은 현상을 해결하고, 효율적인 코드 작성을 달성할 수 있을까요?

 

Template In C++

  일반적인 상황 즉, Int클래스가 어떤 클래스나 함수에 구애받지 않고 독립적인 상황에서 동작하는 클래스라면 위와 같이 정의해도 문제 될 것이 전혀 없습니다. 하지만, Int클래스와 비슷하게 동작하는 클래스들이 생겨날 예정이라고 한다면 얘기는 달라집니다. 이때 사용하는 방법이 Generic Programming 기법입니다. 코드의 효율성을 높이며, 데이터 유형에 구애받을 필요 없이 코드 작성이 이루어지기 때문에 아래와 같은 장점이 존재합니다.

 

  1.  코드 재사용성 - 타입에 구애받지 않기 때문에 재사용성이 당연히 대폭 증가하게 됩니다.

  2.  다형성 - 객체 지향 개념 중 하나인 다형성을 자연스럽게 달성하게 됩니다.

그렇다면 위처럼 언급한 개념들을 코드에서 살펴보도록 하겠습니다. C++에서는 위와 같은 기능을 아주 손쉽게 다룰 수 있게 이미 환경을 마련했습니다. 만약 이해가 안 된다면 다음 문장을 기억하세요, 데이터에 구애받지 않으며, 동일한 코드를 여러 번 작성할 필요 없이 한 번만 작성하면 끝!입니다. 아래 코드를 보도록 하겠습니다.

 

#include <iostream>

using namespace std;

class Type
{
    private:
        int myVar;
    public:
        Type(int c):myVar(c){}
        ~Type(){}
        
        void add(int x);
        void sub(int x);
        void show() const { cout << "var : " << myVar << endl; }
};

void Type::add(int x){
    this->myVar += x;
}

void Type::sub(int x){
    this->myVar -= x;
}

int main() {
    Type type(10);
    
    type.add(2);
    type.show();
    type.sub(4);
    type.show();
    return 0;
}

 

Type클래스 내부에는 당연히 정수형 타입의 변수만 인자로 전달 받습니다. 그렇기 때문에 Type클래스의 멤버 함수 add, sub에서 만약 int가 아닌 double형태로 인자를 받았더라면, 컴파일 오류가 발생한다는 사실은 삼척동자도 아는 사실일 것입니다. 하지만 저는 Type클래스를 선언해서 double이던, int 던 연산을 가능케 하고 싶습니다. 어떻게 하는 것이 가장 좋을까요?

 

#include <iostream>

using namespace std;

template <typename T> class Type
{
    private:
        T myVar;
    public:
        Type(T c):myVar(c){}
        ~Type(){}
        
        void add(T x);
        void sub(T x);
        void show() const { cout << "var : " << myVar << endl; }
};

template <typename T>
void Type<T>::add(T x){
    this->myVar += x;
}

template <typename T>
void Type<T>::sub(T x){
    this->myVar -= x;
}

int main() {
    Type<int> type(10);
    Type<double> type2(3.14);
    
    type.add(2);
    type2.add(3.14);
    
    type.show();
    type2.show();
    
    type.sub(1);
    type2.sub(2.28);
    
    type.show();
    type2.show();
    return 0;
}

 

위와 같이 선언되어 있으며, 아래 main()함수를 보게 되면, Type 인스턴스 type과 type 2를 볼 수 있습니다. 그리고 Type 뒤에는 <>를 이용해서 내부에 타입이 선언되어있는 것 또한 확인할 수 있습니다. 그러니까 type은 정수형 Type인스턴스가 되는 것이며, type 2는 실수형 Type인스턴스가 되는 것이죠. 연산 또한 자유롭게 가능한 것을 확인할 수 있습니다.

 

template class의 문법은 아래와 같이 간단하게 작성해서 사용할 수 있습니다.

 

template<typename T> class ...

 

두개의 generic타입 또한 받아도 상관없습니다 아래처럼 말이죠.

 

template <typename T, typename U> class ...

 

이상 template 클래스에 대해서 알아보았습니다. 쉽다면 쉽고, 어렵다면 어렵게 느껴지겠지만, 연습할 때에는 별거 아닌 클래스에도 template클래스를 적용해서 코드를 작성하다 보면, 이해를 쉬이 하실 수 있을 것이라고 생각됩니다!!

 

감사합니다~~

728x90

댓글