0

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

现在我有一个演员类,它通过一个方法接收一个 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);
}
4

2 回答 2

4

您声称它不会编译,但以下测试为我编译并运行(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);
}
于 2012-11-14T21:34:14.577 回答
2

我敢打赌你使用的是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::shared_ptr可以std::make_shared<T>()节省一次动态分配,甚至可以节省一半的共享状态内存开销。您还应该std::shared_ptr作为对函数的引用传递,或者至少像我一样将其移动到新值。您还可以考虑使用std::unique_ptrwhich 使其更加有效(没有共享状态内存开销和线程安全引用计数)并使设计更好(明确所有权)。您可以以非常相似的方式使用:

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));
}
于 2012-11-14T21:48:59.333 回答