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

2021. 3. 21. 23:59·C++/Templates
목차
  1. 예제
  2. 헤더 파일과 .cpp 파일의 분리
  3. Explicit Instantiation

클래스 템플릿 (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
  1. 예제
  2. 헤더 파일과 .cpp 파일의 분리
  3. Explicit Instantiation
'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)
  • 블로그 메뉴

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

  • 공지사항

  • 인기 글

  • 태그

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

  • 최근 글

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

개인정보

  • 티스토리 홈
  • 포럼
  • 로그인
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.