让我们想想一个可能实现的CreateInfoObject
:
void InfoFactory::CreateInfoObject(AbstractInfo** info)
{
*info = new SuperInfo;
}
现在,SuperInfo
和MyInfoObject
不具备共同的权利什么?
这就是为什么,在一般情况下,以下是被禁止的:
struct Base {};
struct D1: Base {};
struct D2: Base {};
int main(int argc, char* argv[])
{
Base** base = nullptr;
D1* d = nullptr;
base = d;
}
因为这将使D1
指向的东西无关。
有几种解决方案:
// 1. Simple
AbstractInfo* info = nullptr;
fc.CreateInfoObject(info);
// 2. Better interface
std::unique_ptr<AbstractInfo> info = fc.CreateInfoObject();
然后,如果你知道肯定地说,你,其实,一个MyInfoObject
你可以使用:
MyInfoObject* myInfo = static_cast<MyInfoObject*>(info);
,或者如果您不确定:
MyInfoObject* myInfo = dynamic_cast<MyInfoObject*>(info);
如果有的话,它将设置myInfo
到nullptr
info
未指向MyInfoObject
(或派生)的实例。
但请记住,您的界面真的很可怕。它非常C-ISH,不清楚记忆是否真的被分配......以及谁负责处理它,如果是的话。
编辑:
在良好 C++风格,我们使用RAII双方表示所有权和确保清理。 RAII是众所周知的,虽然不是很具有说服力,但我自己更喜欢新的SBRM(Scope Bound Resources Management)。
的想法是,而不是使用裸指针,这并不表明任何所有权(即你必须调用删除就可以了?),你应该使用智能指针,例如像unique_ptr
。
您也可以使用方法的返回参数,以避免有两个步骤的初始化过程(首先创建指针,然后使其指向一个对象)。这里有一个简明的例子:
typedef std::unique_ptr<AbstractInfo> AbstractInfoPtr;
// Note: if you know it returns a MyInfoObject
// you might as well return std::unique_ptr<MyInfoObject>
AbstractInfoPtr InfoFactory::CreateInfoObject()
{
return AbstractInfoPtr(new MyInfoObject());
}
// Usage:
int main(int argc, char* argv[])
{
InfoFactory factory;
AbstractInfoPtr info = factory.CreateInfoObject();
// do something
} // info goes out of scope, calling `delete` on its pointee
在这里,关于所有权没有歧义。
此外,请注意你如何更好地理解你的问题在这里:
std::unique_ptr<MyInfoObject> info = factory.CreateInfoObject();
不会编译,因为你不能转换AbstractInfo*
为MyInfoObject*
,而无需使用static_cast
或dynamic_cast
。
编辑讨论您的评论! – 2010-09-27 21:10:18
@Tony:我编辑了我的答案,提供了一个替代接口的提案。 – 2010-09-28 06:28:24
非常感谢您的解释。现在我还可以从检索到的AbstractInfoPtr中进行下拉式转换为派生的对象吗?这是一个好主意吗? – 2010-09-28 07:25:38