【发布时间】:2010-08-13 17:27:50
【问题描述】:
这有点做作,但假设我有一个这样的类接口:
class IResource;
class IResourceContainer
{
public:
virtual ~IResourceContainer() {}
virtual void AddResource(const std::string& rStrName,
std::auto_ptr<IResource> apResource)=0;
virtual IResource& GetResource(const std::string& rStrName)=0;
};
我有一个此类的实现,其中包含字符串到 IResource 类型的映射。如果我要像这样添加自己的资源:
container.AddResource("foo", std:auto_ptr<IResource>( new CFooResource);
然后再检索资源引用
CFooResource& fooResource = container.GetResource(); // error
这不会编译,因为我需要将 IResource 向下转换为 CFooResource。我曾考虑通过让 GetResource 采用模板参数来隐藏这一点,该参数在内部向下转换类型,但显然,模板和纯接口不会出错。我目前的替代方法是将转换隐藏在调用 boost::polymorphic_downcast 的 CastResource 函数中,但我仍然对客户端需要转换资源的想法感到不快。
例如:
CFooResource& fooResource = CastResource<CFooResource&>(container.GetResource());
所以我想我的问题是:有没有更好的方法来保存指向不需要用户明确向下转换的泛型类型的指针?我觉得有一种模板化的方式可以做到这一点,但我没有看到。另外,我制作了这个界面,以便客户可以在需要时轻松地在测试中模拟它。
谢谢。
【问题讨论】:
-
我想说
dynamic_cast是这里最好的解决方案。您必须意识到该函数必须返回的不是派生程度最高的类型(这在技术上是不可能的),而是用户期望的类型。或NULL否则。这正是dynamic_cast所做的。将其打包在模板中不会改变以下事实:1)它仍然是由用户控制的 dynamic_cast 以及 2)它不一定是派生度最高的类型。