学习 c++11 智能指针,它不会让我像指针一样使用隐式转换吗?

Learning c++11 smart pointer, it won't let me use implicit conversion like a pointer can?

本文关键字:指针 一样 转换 智能 c++11 学习      更新时间:2023-10-16

我有一个ISceneNode接口,还有一个SceneNode基类。从 SceneNode 类派生出 MeshNode、AnimNode、LightNode、CameraNode 等。

现在我有一个 actor 类,它通过一个方法接收一个shared_ptr并将其存储在字段中。

我希望能够做的是将任何 std::shared_ptr 或其他派生类发送到接受shared_ptr的函数中。

对于裸指针,这将是一个隐式转换。

我想出的解决方案是为每个派生编写一个重载,然后使用 dynamic_pointer_cast 在方法中强制转换它。 这太讨厌了,应该有更好的方法。

有没有办法获得隐式强制转换,或者我不知道的更好的方法来解决这个问题?处理这个问题的正确方法是什么?

void SomeFunc()
{
    std::shared_ptr<MeshNode> pMeshNode( new MeshNode() );
    gActor.SetNode( pMeshNode );  // won't compile.
    // or do i have to do it like this
    gActor.SetNode( std::dynamic_pointer_cast<ISceneNode> (pMeshNode) );
}
void Actor::SetNode( std::shared_ptr<ISceneNode> pNode )
{
    mpNode = pNode;
}
// or do I have to do it like this?  Making an over load for each derived.
void Actor::SetNode( std::shared_ptr<MeshNode> pMeshNode )
{
    mpNode = std::dynamic_pointer_cast<ISceneNode> (pMeshNode);
}

你声称它不会编译,但下面的测试为我编译和运行(VS2012,Clang,G++)。您应该发布您收到的错误,因为它很可能是其他错误。

#include <memory>
struct IBase {};
struct Derived : IBase {};
void Foo(std::shared_ptr<IBase> p) {}
int main()
{
    std::shared_ptr<Derived> d;
    Foo(d);
}

>我敢打赌你使用的是VS2010?我发现那里的智能指针支持存在一些问题?在具有更好 C++11 支持的编译器上(例如。VS2012,gcc,clang)它应该编译得很好。但是,我建议您进行一些扩展:

class Actor {
  std::shared_ptr<ISceneNode> mpNode;
public:
  void SetNode(std::shared_ptr<ISceneNode> pNode)
  { mpNode = std::move(pNode); }
};
void SomeFunc()
{
  gActor.SetNode(std::make_shared<MeshNode>());
}
最好使用

std::make_shared<T>() 分配std::shared_ptr,这样可以节省一个动态分配,甚至最多可以节省共享状态内存开销的一半。您还应该将std::shared_ptr作为对函数的引用传递,或者至少像我一样将其移动到新值。您还可以考虑使用 std::unique_ptr,使其更有效(无共享状态内存开销和线程安全引用计数)并使设计更好(明确所有权)。你可以用非常类似的方式使用:

class Actor {
  std::unique_ptr<ISceneNode> mpNode;
public:
  void SetNode(std::unique_ptr<ISceneNode> pNode)
  { mpNode = std::move(pNode); }
};
void SomeFunc()
{
  gActor.SetNode(std::unique_ptr<MeshNode>(new MeshNode));
}