C++ 클래스 템플릿 (Class Templates)

2021. 3. 21. 23:59·C++/Templates

클래스 템플릿 (Class Templates)

  • 클래스에도 템플릿을 적용할 수 있다.

예제

  • 템플릿을 사용하지 않은 예제

    main.cpp

    #include "MyArray.h"
    
    int            main()
    {
      MyArray my_array(10);
    
      for (int i = 0; i < my_array.getLength(); ++i)
        my_array[i] = i * 10;
    
      my_array.print();
    }
    
    /* stdout
    0 10 20 30 40 50 60 70 80 90
    */

    MyArray.h

    #pragma once
    #include <iostream>
    #include <cassert>
    
    class MyArray
    {
      int  length_;
      int* data_;
    
    public:
      MyArray()
      {
        length_ = 0;
        data_ = nullptr;
      }
    
      MyArray(const int& length_in)
      {
        data_ = new int[length_in];
        length_ = length_in;
      }
    
      ~MyArray()
      {
        reset();
      }
    
      void reset()
      {
        delete[] data_;
        data_ = nullptr;
        length_ = 0;
      }
    
      int& operator[](int index)
      {
        assert(index >= 0 && index < length_);
        return data_[index];
      }
    
      int getLength()
      {
        return length_;
      }
    
      void print()
      {
        for (int i = 0; i < length_; ++i)
          std::cout << data_[i] << ' ';
        std::cout << std::endl;
      }
    };

  • 템플릿을 적용한 예제

    main.cpp

    #include "MyArray.h"
    
    int            main()
    {
      MyArray<int> my_array(10);
    
      for (int i = 0; i < my_array.getLength(); ++i)
        my_array[i] = i * 10;
    
      my_array.print();
    }
    
    /* stdout
    0 10 20 30 40 50 60 70 80 90
    */

    MyArray.h

    #pragma once
    #include <iostream>
    #include <cassert>
    
    template<typename T>
    class MyArray
    {
      int        length_;
      T*        data_;
    
    public:
      MyArray()
      {
        length_ = 0;
        data_ = nullptr;
      }
    
      MyArray(const int& length_in)
      {
        data_ = new T[length_in];
        length_ = length_in;
      }
    
      ~MyArray()
      {
        reset();
      }
    
      void reset()
      {
        delete[] data_;
        data_ = nullptr;
        length_ = 0;
      }
    
      T& operator[](int index)
      {
        assert(index >= 0 && index < length_);
        return data_[index];
      }
    
      int getLength()
      {
        return length_;
      }
    
      void print()
      {
        for (int i = 0; i < length_; ++i)
          std::cout << data_[i] << ' ';
        std::cout << std::endl;
      }
    };
    • main.cpp 에서 다른 자료형을 넣어도 작동한다.

      #include "MyArray.h"
      
      int            main()
      {
        MyArray<double> my_array(10);
      
        for (int i = 0; i < my_array.getLength(); ++i)
          my_array[i] = i * 0.5;
      
        my_array.print();
      }
      
      /* stdout
      0 0.5 1 1.5 2 2.5 3 3.5 4 4.5
      */
      #include "MyArray.h"
      
      int            main()
      {
        MyArray<char> my_array(10);
      
        for (int i = 0; i < my_array.getLength(); ++i)
          my_array[i] = i + 65;
      
        my_array.print();
      }
      
      /* stdout
      A B C D E F G H I J
      */

헤더 파일과 .cpp 파일의 분리

  • 헤더에 함수를 정의했는데, 이를 .cpp 파일로 분리해야 한다.

  • 템플릿을 사용하면 이 과정이 살짝 번거롭다.

  • 일단 헤더 파일에서만 print 함수를 분리해보면 다음과 같다.

    MyArray.h

    #pragma once
    #include <iostream>
    #include <cassert>
    
    template<typename T>
    class MyArray
    {
      int        length_;
      T*        data_;
    
    public:
      MyArray()
      {
        length_ = 0;
        data_ = nullptr;
      }
    
      MyArray(const int& length_in)
      {
        data_ = new T[length_in];
        length_ = length_in;
      }
    
      ~MyArray()
      {
        reset();
      }
    
      void reset()
      {
        delete[] data_;
        data_ = nullptr;
        length_ = 0;
      }
    
      T& operator[](int index)
      {
        assert(index >= 0 && index < length_);
        return data_[index];
      }
    
      int getLength()
      {
        return length_;
      }
    
      void print();
    };
    
    template<typename T>
    void MyArray<T>::print()
    {
      for (int i = 0; i < length_; ++i)
        std::cout << data_[i] << ' ';
      std::cout << std::endl;
    }
    • 이대로 컴파일하면 아무 문제가 없다.
  • 다음은 MyArray.cpp 파일로 옮기는 과정이다.

    • 헤더 파일에서 분리한 함수 정의 부분을 잘라내서, .cpp 파일에 그대로 붙여넣기한다.

      MyArray.cpp

      #include "MyArray.h"
      
      template<typename T>
      void MyArray<T>::print()
      {
        for (int i = 0; i < length_; ++i)
          std::cout << data_[i] << ' ';
        std::cout << std::endl;
      }
      error LNK2019: unresolved external symbol "public: void __cdecl MyArray<char>::print(void)" (?print@?$MyArray@D@@QEAAXXZ) referenced in function main
      • main.cpp에서 MyArray.cpp에 정의된 함수의 body 내용을 알 수 없기 때문에 발생하는 문제라고 한다.

        • 템플릿의 작동 원리를 알아야 완벽하게 파악할 수 있을 것 같다.
      • main.cpp에서 MyArray.cpp를 include 하면 해결되긴 하는데, 이렇게 하는 것은 좋지 않다고 한다.

      • 대신 explicit instantiation을 해야하는데, 명시적으로 템플릿을 적용하는 것이다.


Explicit Instantiation

  • 클래스나 함수에 적용할 템플릿을 명시해주는 것이다.

    MyArray.cpp

    #include "MyArray.h"
    
    template<typename T>
    void MyArray<T>::print()
    {
      for (int i = 0; i < length_; ++i)
        std::cout << data_[i] << ' ';
      std::cout << std::endl;
    }
    
    template class MyArray<char>;
    template void MyArray<double>::print();
저작자표시 (새창열림)

'C++ > Templates' 카테고리의 다른 글

C++ 클래스 템플릿 특수화 (Class Templates Specialization)  (0) 2021.03.22
C++ 함수 템플릿 특수화 (Function Templates Specialization)  (0) 2021.03.22
C++ 자료형이 아닌 템플릿 매개변수 (Non-type Templates Parameters)  (0) 2021.03.21
C++ 함수 템플릿 (Function Templates)  (0) 2021.03.21
C++ 템플릿 (Templates)  (0) 2021.03.21
'C++/Templates' 카테고리의 다른 글
  • C++ 함수 템플릿 특수화 (Function Templates Specialization)
  • C++ 자료형이 아닌 템플릿 매개변수 (Non-type Templates Parameters)
  • C++ 함수 템플릿 (Function Templates)
  • C++ 템플릿 (Templates)
Caniro
Caniro
  • Caniro
    Minimalism
    Caniro
  • 전체
    오늘
    어제
    • 분류 전체보기 (317)
      • Algorithm (13)
        • 알기 쉬운 알고리즘 (10)
        • Search (1)
        • Sort (2)
      • Arduino (0)
      • C++ (185)
        • Class (46)
        • Exception (6)
        • Library (51)
        • Overloading (10)
        • SmartPointer (5)
        • Syntax (33)
        • TBC++ (23)
        • Templates (9)
        • VisualStudio (2)
      • Embedded (1)
      • Git (4)
      • Java (5)
      • Linux (16)
        • Error (1)
        • Linux Structure (11)
      • MacOS (7)
      • OS (1)
        • Concurrency (1)
      • Python (21)
        • Class (1)
        • Function (2)
        • Syntax (17)
      • Raspberrypi (9)
      • Review (1)
      • Utility (12)
        • VSCode (5)
        • VirtualBox (3)
      • Web (8)
        • Nginx (1)
        • React (3)
        • Django (1)
      • Windows (20)
        • Registry (3)
        • WSL (1)
        • DeviceDriver (6)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    unix
    EXCLUDE
    logi options
    Solaris 10
    윈도우 명령어
    Workspace
    맥북 카카오톡 알림 안뜸
    제외
    시스템 복구
    SunOS 5.1
    로지텍 마우스 제스처
    citrix workspace
    vscode
    mspaint
    MacOS
    스프링
    Windows 11
    백기선
    dism
    SFC
    윈도우
    spring
    그림판
    windows
    java
    알림
    스프링 프레임워크 핵심 기술
    KakaoTalk
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
Caniro
C++ 클래스 템플릿 (Class Templates)
상단으로

티스토리툴바