문제

나는 이것이 전에 요청 된 것 같은 느낌이 들지만, 그것을 찾을 수 없으며, Google에서 유용한 것을 찾을 수 없다. 어쩌면 "공분산"은 내가 찾고있는 단어가 아니지만이 개념은 기능의 공분산 반환 유형과 매우 유사하므로 아마도 맞다고 생각합니다. 다음은 내가하고 싶은 일이며 컴파일러 오류를 제공합니다.

class Base;
class Derived : public Base;

SmartPtr<Derived> d = new Derived;
SmartPtr<Base> b = d; // compiler error

그 수업이 완전히 살아 났다고 가정합니다 ... 나는 당신이 아이디어를 얻는다고 생각합니다. 변환 할 수 없습니다 SmartPtr<Derived> a SmartPtr<Base> 불분명 한 이유 때문에. 나는 이것이 C ++와 다른 많은 언어에서 정상이라는 것을 기억하지만, 현재 나는 이유를 기억할 수 없다.

내 루트 질문은 :이 과제 작업을 수행하는 가장 좋은 방법은 무엇입니까? 현재 포인터를 꺼내고 있습니다 SmartPtr, 기본 유형으로 명시 적으로 업 캐스트 한 다음 새로 포장 SmartPtr 적절한 유형 중 SmartPtr 클래스는 침입 참조 계수를 사용합니다). 길고 지저분합니다. 특히 내가 마무리해야 할 때 SmartPtr 또 다른 물체에서 ... 어떤 지름길이 있습니까?

도움이 되었습니까?

해결책

카피 생성자와 할당 연산자는 모두 다른 유형의 SmartPtr을 가져 와서 포인터를 서로 복사하려고 시도해야합니다. 유형이 호환되지 않으면 컴파일러가 불만을 제기하고 호환되는 경우 문제를 해결했습니다. 이 같은:

template<class Type> class SmartPtr
{
    ....
    template<class OtherType> SmartPtr(const SmartPtr<OtherType> &blah) // same logic as the SmartPtr<Type> copy constructor

    template<class OtherType> SmartPtr<Type> &operator=(const SmartPtr<OtherType> &blah) // same logic as the SmartPtr<Type> assignment operator
};

다른 팁

SmartPtr<Base> 그리고 SmartPtr<Derived> 두 가지 뚜렷한 인스턴스화입니다 SmartPtr 주형. 이 새로운 클래스는 그 상속을 공유하지 않습니다 Base 그리고 Derived 하다. 따라서, 당신의 문제.

이 과제 작업을 수행하는 가장 좋은 방법은 무엇입니까?

 SmartPtr<Base> b = d; 

과제 연산자를 호출하지 않습니다. 이것은 카피 -CTOR를 호출하며 (대부분의 경우 사본은 피해를 입히고) 다음과 같습니다.

 SmartPtr<Base> b(d); 

a SmartPtr<OtherType> 그리고 그것을 구현하십시오. 과제 연산자도 마찬가지입니다. SmartPtr의 의미론을 염두에두고 Copy-CTOR 및 OP = OP =를 작성해야합니다.

템플릿은 공분산이 아니며, 좋습니다. 다음 경우 어떤 일이 일어날 지 상상해보십시오.

vector<Apple*> va;
va.push_back(new Apple);

// Now, if templates were covariants, a vector<Apple*> could be
// cast to a vector<Fruit*>
vector<Fruit*> & vf = va;
vf.push_back(new Orange); // Bam, we just added an Orange among the Apples!

당신이하려는 일을 달성하기 위해서는 SmartPointer 클래스에는 다른 SmartPointer 또는 다른 유형의 포인터를 사용하는 템플릿 생성자가 있어야합니다. 당신은 boost :: shared_ptr을 볼 수 있습니다.

template <typename T>
class SmartPointer {

    T * ptr;

  public:
    SmartPointer(T * p) : ptr(p) {}
    SmartPointer(const SmartPointer & sp) : ptr(sp.ptr) {}

    template <typename U>
    SmartPointer(U * p) : ptr(p) {}

    template <typename U>
    SmartPointer(const SmartPointer<U> & sp) : ptr(sp.ptr) {}

    // Do the same for operator= (even though it's not used in your example)
};

에 달려 있습니다 SmartPtr 수업. 복사 생성자 (또는 귀하의 경우 할당 연산자)가있는 경우 SmartPtr<T>, 여기서 t는 구성된 유형 인 경우 작동하지 않을 것입니다. SmartPtr<T1> 관련이 없습니다 SmartPtr<T2> T1과 T2가 상속과 관련이 있더라도.

그러나 SmartPTR이있는 경우 템플릿 템플릿 매개 변수와 함께 생성자/할당 연산자를 복사하십시오 TOther, 그것은 받아들입니다 SmartPtr<TOther>, 그런 다음 작동해야합니다.

SmartPTR 클래스를 제어한다고 가정하면 솔루션은 템플릿 생성자를 제공하는 것입니다.

template <class T>
class SmartPtr
{
    T *ptr;
public:

    // Note that this IS NOT a copy constructor, just another constructor that takes 
    // a similar looking class.
    template <class O>
    SmartPtr(const SmartPtr<O> &src)
    {
        ptr = src.GetPtr();
    }
    // And likewise with assignment operator.
};

T 유형과 O 유형이 호환되면 작동하지 않으면 컴파일 오류가 발생합니다.

가장 쉬운 것은 다음에 따라 다른 smartptr로 자동 변환을 제공하는 것입니다.

template <class T>
class SmartPtr
{
public:
    SmartPtr(T *ptr) { t = ptr; }
    operator T * () const { return t; }
    template <class Q> operator SmartPtr<Q> () const
    { return SmartPtr<Q>(static_cast<Q *>(static_cast<T *>(* this))); }
private:
    T *t;
};

이 구현은 변환 연산자 템플릿이 스마트 포인터의 의미론에 대해 알 필요가 없다는 점에서 강력하므로 참조 계산 등을 복제 할 필요가 없습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top