【发布时间】:2015-01-04 03:28:38
【问题描述】:
我有一个抽象的UI 类,它需要能够向用户询问一些输入。
这个函数是模板化的,因为可以要求不同的东西。
但是,这个函数也必须是虚拟的,因为我希望 UI 的派生类能够
提供他们自己的实现(CommandLineUI 的行为需要与
WebBasedUI)。
class UI {
// ...
public:
// ask some input
template<T>
virtual T askFor(const std::string& mesg) const = 0;
// ask but provide default fallback
template<T>
virtual T askFor(const std::string& mesg, const T& def) const = 0;
}
class CommandLineUI : UI {
// ...
public:
template<T>
virtual T askFor(const std::string& mesg) const {
// implementation details
}
template<T>
virtual T askFor(const std::string& mesg, const T& def) const {
// implementation details
}
}
然而,上面的代码不起作用,因为模板化的方法在 C++ 中不能是虚拟的, 出于我上面的原因。
我阅读了一些关于访问者模式或类型擦除能够解决此问题的内容,但我不知道如何解决。 (我试图将答案中找到的示例翻译为 类似的堆栈溢出问题,但没有成功)。
【问题讨论】:
-
模板函数不能为
virtual。 -
虚函数不能是模板,因为在编译时必须知道重载的数量。但是,如果您在某处的代码中执行
ui.askFor<not_yet_used_type>(),则在不同编译单元中创建的对象的 vtable 将丢失该条目。 -
这里的问题是你试图混合运行时和编译时多态性。为什么不定义一组支持的类型?通常,您可以很好地使用 int、float、string、datetime、它们的列表、它们的字典之类的集合。
-
看来您并没有真正考虑过这个设计。你将如何实现
CommandLineUI::askFor?当我拨打ui->askFor<Frobnicator>("Enter frobnicator:")时会发生什么? -
askFor适用于可以从流中读取的所有内容。为int、double、string等编写自定义函数的问题是实现代码会非常重复,askFor函数真的很复杂……
标签: c++ templates inheritance polymorphism virtual