使用派生类的std::unique_ptr

33

我有一个关于C++11指针的问题。具体来说,如何将一个基类的unique pointer转换为派生类的指针?

class Base
{
public:
   int foo;
}

class Derived : public Base
{
public:
   int bar;
}

...

std::unique_ptr<Base> basePointer(new Derived);
// now, how do I access the bar member?

这应该是可以实现的,但我无法想出如何做到。每次尝试使用时

basePointer.get()

我最终得到了可执行文件崩溃的结果。

提前感谢,任何建议将不胜感激。


3
你能展示一份导致进程崩溃的完整(但最小化)代码示例吗?仅仅使用basePointer.get()肯定不是问题所在。 - jogojapan
@jogojapan 我解决了我的问题。我使用了至少5组括号进行一些非常奇怪的转换。我相信这只是一些愚蠢的错误,但我已经改正了它,不记得我做了什么。Captain Obvlious的答案对我有用。感谢你们的帮助! - Lukas Schmit
1个回答

57

如果它们是多态类型,并且您只需要指向派生类型的指针,请使用 dynamic_cast

Derived *derivedPointer = dynamic_cast<Derived*>(basePointer.get());
如果它们不是多态类型,只需要指向派生类型的指针,使用static_cast并祈求最好的结果即可。
Derived *derivedPointer = static_cast<Derived*>(basePointer.get());

如果您需要转换包含多态类型的unique_ptr

Derived *tmp = dynamic_cast<Derived*>(basePointer.get());
std::unique_ptr<Derived> derivedPointer;
if(tmp != nullptr)
{
    basePointer.release();
    derivedPointer.reset(tmp);
}

如果您需要转换包含非多态类型的unique_ptr:

std::unique_ptr<Derived>
    derivedPointer(static_cast<Derived*>(basePointer.release()));

你确定在执行basePointer.release()时没有内存泄漏吗? - Marc
3
@Marc,它之所以安全是因为release()reset()都是noexcept的,所以除非你在这个函数外做了非常糟糕的事情,否则原始指针将始终最终成为派生指针并被正确销毁。 - meneldal
1
这对某些人来说可能很明显,但请注意,您正在从basePointer中窃取资源,而这并不总是您在unique_ptr转换中所希望的。 - Masadow
3
如果这不是你想要的,那么你就不需要一个“独特”的指针。 - Daniel McLaury
2
答案存在问题。 是的,static_cast也支持多态类型。只有在你不确定转换是否能够成功时才应该使用dynamic_cast(并在这种情况下像你所做的一样测试它是否返回了null)。 - Johan Boulé
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接