【发布时间】:2015-07-07 03:56:01
【问题描述】:
因为以下是非法的:
struct A {
template <typename T>
virtual T* foo() = 0;
};
struct B : A {
template <typename T>
virtual T* foo() override {return new T;} // Simple example here.
};
template <typename T>
T* bar (A* a) {
return a->foo<T>(); // The need for the virtual method.
}
并且模板只出现在返回类型中,我想到了一个(天真的?)使用重载的解决方法:
#include <iostream>
struct Base { virtual void show() const = 0; };
struct Object : Base { virtual void show() const override {std::cout << "I am an Object.\n";} };
struct Thing : Base { virtual void show() const override {std::cout << "I am a Thing.\n";} };
struct Blob : Base { virtual void show() const override {std::cout << "I am a Blob.\n";} };
struct A {
virtual Object* foo (Object&&) = 0;
virtual Thing* foo (Thing&&) = 0;
virtual Blob* foo (Blob&&) = 0;
};
struct B : A {
virtual Object* foo (Object&&) override {return fooHelper<Object>();}
virtual Thing* foo (Thing&&) override {return fooHelper<Thing>();}
virtual Blob* foo (Blob&&) override {return fooHelper<Blob>();}
private:
template <typename T>
T* fooHelper() {return new T;} // Simple example here.
};
template <typename T>
T* bar (A* a) {
return a->foo(T{});
}
int main() {
B* b = new B;
Base* list[] = {bar<Object>(b), bar<Thing>(b), bar<Blob>(b)};
for (const Base* x : list) x->show();
}
这个方案的问题在于,只有在T的类型不多的情况下才可行。但如果有呢?此外,现在T 的新类型在以后引入时存在维护问题。
有人能想出比这更好的解决方案吗?已知的访问者模式作为虚拟模板解决方法在这里不适用(我不认为),因为模板没有出现在参数中。
【问题讨论】:
-
你需要协变返回类型吗?
-
@marom 我的
T* create (A* a)功能是我的目标。我仅将协变返回类型用作解决方案,而不是目标本身。如果有另一种没有协变返回类型的方法,那就太好了。 -
您的示例中有很多内存泄漏。
-
您是否需要您的函数参数 (
a) 成为类层次结构的一部分?否则它的类型可能只是另一个模板参数。 -
你的目标是什么?让
A尽可能简单,比如只返回Base并且可能有一个foo函数?A的子类有多少,它们都必须支持从Base子类化的所有类型吗?编译时类型安全和A接口的强制执行对你来说是绝对必要的还是你愿意做出妥协?