让我们考虑一下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);
如果info 没有指向MyInfoObject 的实例(或派生的),则将myInfo 设置为nullptr。
但请记住,您的界面真的很糟糕。它非常 C-ish,不清楚是否实际分配了内存......如果是,谁负责处理它。
编辑:
在good C++ 风格中,我们使用 RAII 来表示所有权并确保清理。 RAII 是众所周知的,虽然不是很有指示性,但我自己更喜欢新的 SBRM(范围绑定资源管理)。
这个想法是,而不是使用一个裸指针,它不表明任何关于所有权的事情(即你必须在它上面调用 delete 吗?)你应该使用一个智能指针,例如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();
无法编译,因为不使用 static_cast 或 dynamic_cast 就无法将 AbstractInfo* 转换为 MyInfoObject*。