我一直在寻找一种同时使用模板和多态性的方法。这是我的问题的简化版本:
#include <iostream>
#include <vector>
using std::cout;
using std::endl;
//*******************************************************************
//*******************************************************************
struct DerivedStuff1
{
static void eval() { cout << "evaluating DerivedStuff1" << endl; }
};
struct DerivedStuff2
{
static void eval() { cout << "evaluating DerivedStuff2" << endl; }
};
//*******************************************************************
//*******************************************************************
class BaseClass
{
public:
template<typename StuffType> virtual void eval() const = 0;
};
class DerivedClass1 : public BaseClass
{
public:
template<typename StuffType> virtual void eval() const
{
std::cout << "We are in DerivedClass1: ";
StuffType::eval();
}
};
class DerivedClass2 : public BaseClass
{
public:
template<typename StuffType> virtual void eval() const
{
std::cout << "We are in DerivedClass2: ";
StuffType::eval();
}
};
int main()
{
BaseClass* c1 = new DerivedClass1;
c1->eval<DerivedStuff1>();
c1->eval<DerivedStuff2>();
BaseClass* c2 = new DerivedClass2;
c2->eval<DerivedStuff1>();
c2->eval<DerivedStuff2>();
return 0;
}
此代码无法编译,因为 C++ 中不允许使用虚拟模板函数。我发现了一些解决这个问题的方法(CRTP 等),但没有一个真正令人满意。没有优雅的方法来解决这个问题吗?
最佳答案
visitor pattern将运行时多态性放在一边,并使运行时多态函数模板成为可能。除了模板化之外,它还有其他合法用途,所以我想你可以说它有点优雅。
您的示例如下所示:
#include <iostream>
class DerivedStuff1 {
public:
static void eval() { std::cout << "Evaluating DerivedStuff1\n"; }
};
class DerivedStuff2 {
public:
static void eval() { std::cout << "Evaluating DerivedStuff2\n"; }
};
class DerivedClass1; class DerivedClass2;
class BaseClassVisitor {
public:
virtual void visit(DerivedClass1&) = 0;
virtual void visit(DerivedClass2&) = 0;
};
class BaseClass {
public:
virtual void accept(BaseClassVisitor& v) = 0;
};
class DerivedClass1 : public BaseClass
{
public:
virtual void accept(BaseClassVisitor& v) { v.visit(*this); }
};
class DerivedClass2 : public BaseClass
{
public:
virtual void accept(BaseClassVisitor& v) { v.visit(*this); }
};
template <typename StuffType>
class EvalVisitor : public BaseClassVisitor
{
virtual void visit(DerivedClass1&) {
std::cout << "We are in DerivedClass1: ";
StuffType::eval();
}
virtual void visit(DerivedClass2&) {
std::cout << "We are in DerivedClass2: ";
StuffType::eval();
}
};
int main()
{
EvalVisitor<DerivedStuff1> e1;
EvalVisitor<DerivedStuff2> e2;
BaseClass* c1 = new DerivedClass1;
c1->accept(e1);
c1->accept(e2);
BaseClass* c2 = new DerivedClass2;
c2->accept(e1);
c2->accept(e2);
return 0;
}
当然,Visitor 的所有缺点都适用于此。
关于c++ - C++中的虚拟模板函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45849394/