关于c ++:向下转换shared_ptr< Base>

Downcasting shared_ptr<Base> to shared_ptr<Derived>?

更新:本例中的共享指针与boost中的共享指针类似,但它不支持共享的多态向下转换(或动态指针转换或静态指针转换)。

我正在尝试在不丢失引用计数的情况下初始化指向派生类的共享指针:

1
2
3
4
5
6
7
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++会隐式地把BASIC转换成派生的*。但是,我确实希望代码表示的功能(即,在向下转换基指针时保持引用计数)。我的第一个想法是在基础中提供一个强制转换运算符,以便进行到派生的隐式转换(对于学究:我将检查强制转换是否有效,不用担心):

1
2
3
4
5
6
7
struct Base {
  operator Derived* ();
}
// ...
Base::operator Derived* () {
  return down_cast<Derived*>(this);
}

嗯,没用。似乎编译器完全忽略了我的类型转换运算符。我有什么想法可以让共享的分配工作发挥作用吗?加分:什么类型的Base* const是?我明白,但我明白。在这种情况下,const指的是什么?


您可以使用dynamic_pointer_cast。它由std::shared_ptr支持。

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

另外,我不建议在基类中使用cast运算符。像这样的隐式强制转换可能成为错误和错误的根源。

-更新:如果类型不是多态的,可以使用std::static_pointer_cast


我想你用的是boost::shared_ptr…我想你想要dynamic_pointer_castshared_polymorphic_downcast

然而,这需要多态性类型。

what kind of type Base* const is? const Base* I understand, but Base* const? What does const refer to in this case?

  • const Base *是指向常量Base的可变指针。
  • Base const *是指向常量Base的可变指针。
  • Base * const是指向可变Base的常量指针。
  • Base const * const是指向常量Base的常量指针。

下面是一个最小的例子:

1
2
3
4
5
6
7
8
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的参考计数不变。

shared_polymorphic_downcast将具有与静态强制转换相同的结果,但将触发断言,而不是看起来成功并导致未定义的行为。Base上的引用计数将增加。

参见(死链接):

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.


如果有人带着Boost::Shared_ptr来到这里…

这是您可以向下投射到派生的Boost共享指针的方法。假设派生继承自基。

1
2
3
4
5
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;

确保"base"类/结构至少有一个虚拟函数。虚拟析构函数也可以工作。