我有一个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);
}
答案 0 :(得分: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);
}
答案 1 :(得分: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_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));
}