programing

공유 _ptr 다운 캐스팅

nasanasas 2020. 9. 12. 10:08
반응형

공유 _ptr 다운 캐스팅 shared_ptr로?


업데이트 : 이 예제의 shared_ptr은 Boost의 것과 비슷하지만 shared_polymorphic_downcast (또는 해당 문제에 대해 dynamic_pointer_cast 또는 static_pointer_cast)를 지원하지 않습니다!

참조 횟수를 잃지 않고 파생 클래스에 대한 공유 포인터를 초기화하려고합니다.

struct Base { };
struct Derived : public Base { };
shared_ptr<Base> base(new Base());
shared_ptr<Derived> derived;

// error: invalid conversion from 'Base* const' to 'Derived*'
derived = base;  

여태까지는 그런대로 잘됐다. C ++가 Base *를 Derived *로 암시 적으로 변환 할 것이라고는 예상하지 못했습니다. 그러나 코드로 표현 된 기능 (즉, 기본 포인터를 다운 캐스팅하는 동안 참조 횟수 유지)을 원합니다. 내 첫 번째 생각은 Derived 로의 암시 적 변환이 발생할 수 있도록 Base에 캐스트 연산자를 제공하는 것이 었습니다 (행동 자의 경우 : 다운 캐스트가 유효한지 확인하겠습니다. 걱정하지 마십시오).

struct Base {
  operator Derived* ();
}
// ...
Base::operator Derived* () {
  return down_cast<Derived*>(this);
}

음, 도움이되지 않았습니다. 컴파일러가 내 typecast 연산자를 완전히 무시한 것 같습니다. shared_ptr 할당을 작동시키는 방법에 대한 아이디어가 있습니까? 추가 점수 : 어떤 유형 Base* const입니까? const Base*이해 합니다만 Base* const? 무엇 않습니다 const이 경우 다음을 참조?


사용할 수 있습니다 dynamic_pointer_cast. 에서 지원됩니다 std::shared_ptr.

std::shared_ptr<Base> base (new Derived());
std::shared_ptr<Derived> derived =
               std::dynamic_pointer_cast<Derived> (base);

또한 기본 클래스에서 캐스트 연산자를 사용하지 않는 것이 좋습니다. 이와 같은 암시 적 캐스팅은 버그 및 오류의 원인이 될 수 있습니다.

-업데이트 : 유형이 다형성이 아닌 경우 사용할std::static_pointer_cast 수 있습니다.


나는 당신이 사용하고 있다고 가정합니다 boost::shared_ptr... 나는 당신이 원 dynamic_pointer_cast하거나 shared_polymorphic_downcast.

그러나 여기에는 다형성 유형이 필요합니다.

어떤 유형 Base* const입니까? const Base*이해 합니다만 Base* const? 무엇 않습니다 const이 경우 다음을 참조?

  • const Base *상수에 대한 가변 포인터 Base입니다.
  • Base const *상수에 대한 가변 포인터 Base입니다.
  • Base * constmutable에 대한 상수 포인터 Base입니다.
  • Base const * const상수에 대한 상수 포인터 Base입니다.

다음은 최소한의 예입니다.

struct Base { virtual ~Base() { } };   // dynamic casts require polymorphic types
struct Derived : public Base { };

boost::shared_ptr<Base> base(new Base());
boost::shared_ptr<Derived> derived;
derived = boost::static_pointer_cast<Derived>(base);
derived = boost::dynamic_pointer_cast<Derived>(base);
derived = boost::shared_polymorphic_downcast<Derived>(base);

귀하의 예제가 기본 유형의 인스턴스를 생성하고 캐스트하는 것이 의도적 인 것인지 확실하지 않지만 차이점을 멋지게 설명하는 역할을합니다.

static_pointer_cast의지 "그냥 해." 이로 인해 정의되지 않은 동작 (에 Derived*의해 할당되고 초기화 된 메모리를 가리킴 Base)이 발생하고 충돌이 발생하거나 더 나빠질 수 있습니다. 참조 횟수 base가 증가합니다.

dynamic_pointer_cast널 포인터가 발생합니다. 의 참조 횟수 base는 변경되지 않습니다.

The shared_polymorphic_downcast will have the same result as a static cast, but will trigger an assertion, rather seeming to succeed and leading to undefined behavior. The reference count on base will be incremented.

See (dead link):

Sometimes it is a little hard to decide whether to use static_cast or dynamic_cast, and you wish you could have a little bit of both worlds. It is well known that dynamic_cast has a runtime overhead, but it is safer, whereas static_cast has no overhead at all, but it may fail silently. How nice it would be if you could use shared_dynamic_cast in debug builds, and shared_static_cast in release builds. Well, such a thing is already available and is called shared_polymorphic_downcast.


If somebody gets here with boost::shared_ptr...

This is how you can downcast to the derived Boost shared_ptr. Assuming Derived inherits from Base.

boost::shared_ptr<Base> bS;
bS.reset(new Derived());

boost::shared_ptr<Derived> dS = boost::dynamic_pointer_cast<Derived,Base>(bS);
std::cout << "DerivedSPtr  is: " << std::boolalpha << (dS.get() != 0) << std::endl;

Make sure 'Base' class/struct has at least one virtual function. A virtual destructor also works.

참고URL : https://stackoverflow.com/questions/1358143/downcasting-shared-ptrbase-to-shared-ptrderived

반응형