更新:此示例中的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 *。但是,我确实需要代码表示的功能(即,在向下转换基指针时保持引用计数)。我的第一个想法是在Base中提供一个强制转换运算符,以便可以进行对Derived的隐式转换(对于pedants:我会检查向下转换是否有效,不要担心):
struct Base {
operator Derived* ();
}
// ...
Base::operator Derived* () {
return down_cast<Derived*>(this);
}
嗯,它没有帮助。似乎编译器完全忽略了我的类型转换操作符。任何想法如何使shared_ptr分配工作?加分:Base* const
是什么类型的? const Base*
我理解,但是Base* const
?在这种情况下const
指的是什么?
答案 0 :(得分:77)
您可以使用dynamic_pointer_cast
。它由std::shared_ptr
支持。
std::shared_ptr<Base> base (new Derived());
std::shared_ptr<Derived> derived =
std::dynamic_pointer_cast<Derived> (base);
另外,我不建议在基类中使用强制转换运算符。像这样的隐式投射可能会成为错误和错误的来源。
-Update:如果类型不是多态的,则可以使用std::static_pointer_cast
。
答案 1 :(得分:46)
我假设您正在使用boost::shared_ptr
...我认为您需要dynamic_pointer_cast
或shared_polymorphic_downcast
。
然而,这些需要多态类型。
Base* const
是什么类型的?const Base*
我理解,但是Base* const
?在这种情况下const
指的是什么?
const Base *
是指向常量Base
的可变指针。Base const *
是指向常量Base
的可变指针。Base * const
是指向可变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
上的引用计数将保持不变。
shared_polymorphic_downcast
将具有与静态强制转换相同的结果,但会触发断言,而不是看似成功并导致未定义的行为。 base
上的引用计数将递增。
请参阅(dead link):
有时候决定是使用
static_cast
还是dynamic_cast
还是有点困难,而且您希望自己可以拥有两个世界。众所周知,dynamic_cast具有运行时开销,但它更安全,而static_cast根本没有开销,但它可能会无声地失败。如果可以在调试版本中使用shared_dynamic_cast
,在发布版本中使用shared_static_cast
,那将会有多好。好吧,这样的事情已经可以使用,被称为shared_polymorphic_downcast
。
答案 2 :(得分:4)
如果有人使用boost :: shared_ptr来到这里......
这是您可以向下转换为派生的Boost shared_ptr的方法。假设Derived继承自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;
确保'Base'类/结构至少有一个虚函数。虚拟析构函数也可以工作。