我有一个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));
}