【问题标题】:Function overloading from a base class when all types are not known当所有类型都不知道时从基类重载函数
【发布时间】:2010-11-09 19:29:45
【问题描述】:

我偶然发现了一个问题,乍一看很容易解决,但仔细研究似乎不是。

我的程序中有项目需要处理多种类型,因此我决定以通用、可扩展的方式处理这些项目:

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*。

那么我该如何解决这个问题呢?什么设计模式或模板技巧可以帮助我?

【问题讨论】:

  • 您是否遇到编译时错误?运行时错误?
  • 编译时“没有一个重载可以转换所有参数类型”
  • 好吧,一方面,您的抽象声明不正确。抽象声明后面不应有 {}。 {} 供派生类实现。这也意味着您的 ItemT 类需要实现基类的析构函数。
  • 它被称为带有身体的纯虚拟:非常罕见,但完全合法。

标签: c++ templates inheritance overloading


【解决方案1】:

简单的答案是:在ItemBase 中添加一个虚拟的buildComponent 方法。但是,由于您希望将 GUI 组件分开,我建议使用 Visitor 模式。

一个非常简单的实现包括:

  • ItemBase 中添加单个accept(AbstractVisitorType &amp;) 虚拟方法
  • 通过调用visitor.visit(*this) 在每个派生类中实现此方法,这意味着AbstractVisitorType 必须为可能调用的每个具体类型提供一个虚拟visit 方法(请参阅下面的注释)
  • 提供此访问者的具体实现,它将根据参数类型在每个 visit 重载中实例化适当的 GUI 对象。

但是请注意,访问者模式仅适用于相当稳定的类层次结构:使用 ItemT 模板的新实例化将需要在访问者端进行维护以处理这种新类型(但您最初的想法有同样的问题)。

Modern C++ Design (Andrei Alexandrescu) 第 10 章是一本关于访问者模式的精彩读物。

【讨论】:

  • 是的,我知道我需要同时维护两个类层次结构。你有什么不同的想法我可以使用吗?
  • 访问者模式几乎是完美的。不幸的是,我必须通过在头文件中包含所有这些可覆盖的函数来让这个类知道如何使用它。很遗憾,虚函数不能被模板化。
  • struct Visitor { template void visit(const ItemT &t) { T item = t.m_Data; }; };
  • 很高兴 :) 您可能想在谷歌上搜索非循环访问者以进一步了解(尽管这对您的需求来说有点矫枉过正)
猜你喜欢
  • 2015-06-10
  • 2017-07-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-16
  • 2014-04-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多