我偶然发现了一个问题,一眼就看出这个问题很简单,但是经过仔细研究似乎并不存在。
我的程序中有项目,我需要使用多种类型,因此我决定以通用,可扩展的方式处理这些项目:
class ItemBase
{
public:
virtual ~ItemBase() = 0 {}
// pure virtual class, some extra members
};
template<typename T>
class ItemT : public ItemBase
{
public:
ItemT(const T &data) : m_Data(data) {}
T m_Data;
};
我现在可以在集合中存储任何类型:
std::vector<ItemBase*> items;
这很好。现在我有GUI组件,我想与这个类分开,所以我想根据类型生成GUI组件:
GuiComponent* BuildComponent(ItemT<int> &item)
{
// do whatever based on this type, the int is needed
}
GuiComponent* BuildComponent(ItemT<double> &item)
{
// do whatever based on this type, the double is needed
}
这几乎是漂亮的编码。不幸的是它不起作用。正如该计划所示:
std::vector<ItemBase*> m_Items;
m_Items.push_back(new ItemT<int>(3));
m_Items.push_back(new ItemT<double>(2.0));
BuildComponent(*m_Items[0]);
因为m_Items [0]的类型为ItemBase *。
那么我该如何解决这个问题呢?什么设计模式或模板技巧可以帮助我在这里?
答案 0 :(得分:4)
简单的答案是:在buildComponent
中添加虚拟ItemBase
方法。但是,由于您希望将GUI组件分开,我建议使用Visitor模式。
一个非常简单的实现包括:
accept(AbstractVisitorType &)
ItemBase
虚拟方法
visitor.visit(*this)
在每个派生类中实现此方法,这意味着AbstractVisitorType
必须为可能调用的每个具体类型提供虚拟visit
方法(请参阅下面的注释) )visit
重载中实例化相应的GUI对象。但请注意,访问者模式仅适用于相当稳定的类层次结构:使用ItemT模板的新实例化将需要访问者侧的维护来处理此新类型(但您的初始想法具有相同的问题)。
现代C ++设计的第10章(Andrei Alexandrescu)是关于访客模式的精彩读物。