ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Effective C++...43
    일지 2022. 8. 19. 07:27

    "호환되는 모든 타입"을 받아들이는 데는 멤버 함수 템플릿이 직방!

    스마트 포인터와 일반 포인터

    기본적으로 스마트 포인터는 "++" 연산을 통해 다음 노드로 이동하는 등 포인터에서 지원하지 않는 다양한 기능을 지원한다. 다만 일반 포인터와 달리 스마트 포인터는 암시적 변환을 지원하지 않는다.


    class Top{ ... };

    class Middle : public Top{ ... };

    class Bottom : public Middle{ ... };

    // 스마트 포인터는 다음과 같은 암시적 변환이 지원되지 않는다.

    Top* pt1 = new Middle;

    Top* pt2 = new Bottom;

    const Top* pct2 = pt1;


     

    스마트 포인터의 암시적 변환 지원

    이를 위해서 특정 타입의 생성자를 만드는 게 아닌 생성자를 만들어주는 템플릿 함수, 멤버 함수 템플릿을 응용하면 된다.


    template<typename T>

    class SmartPtr {

    public:

        template<typename U>

        SmartPtr(const smartPtr<U>& other); // 복사 생성자를 자동 생성한다.

    };


     

    다만 이런식으로 사용하면 기본 클래스로의 변환 외에도 기본 클래스에서 파생 클래스로의 변환도 허용되고, 심지어 int*에서 double*로 변환도 발생할 수 있다.

     

    이를 막기 위해서는 SmartPtr내부에 T타입 포인터를 두고 이를 초기화 해주는 방식으로 T로 암시적 변환이 가능한 것에 대해서만 컴파일이 되도록 만들면 된다.


    template<typename T>

    class SmartPtr {

    public:

        template<typename U>

        SmartPtr(const smartPtr<U>& other)

            : heldPtr(other.get()) { ... }

        T* get() const { return heldPtr; }

    private:

        T* heldPtr;

    };


     

    마지막으로 TU가 같은 경우를 제대로 처리하기 위해서는 기본 복사 생성자들도 생성을 해줘야 한다. C++의 원칙에 따라 복사 생성자를 사용자화 했을 때 기본 복사 생성자는 만들어지지 않기 때문이다.

     

    댓글

Designed by Tistory.