我正试图以参数方式实现访问者模式的修改版本,以这种方式避免每个具体元素过载的“通用访问者”,但是,由于我没有很多经验在模板编程中我不知道如何完成“模式”。
代码:
// test.cpp
#include <iostream>
#include <vector>
using namespace std;
struct Base
{
virtual ~Base() {}
virtual void visit() = 0;
};
template<typename Visitor>
struct ElementBase : public Base
{
// No virtual.
void visit()
{
_e.visit(this);
}
private:
Visitor _e;
};
// Atoms.
template<typename Visitor>
struct ElementA : public ElementBase<Visitor>
{
ElementA() : a(5) {}
int a;
};
// Visitors.
struct VisitorA
{
void visit(ElementBase<VisitorA> *a)
{
ElementA<VisitorA>* elto = dynamic_cast<ElementA<VisitorA>*>(a);
cout << elto->a << endl;
}
/*
void visit(ElementA<VisitorA> *a)
{
cout << a->a << endl;
}
*/
};
std::vector<Base*> v;
int main()
{
v.push_back(new ElementA<VisitorA>());
for (auto i : v)
i->visit();
}
这很好,输出为5(正如预期的那样)。但我假装的是直接使用VisitorA中“访问”的第二个(注释)版本。
显然,这不起作用,因为“this”的类型为ElementBase&lt; ...&gt; *。
如何将指针“this”向下转换为ElementBase中的实际派生类?
答案 0 :(得分:3)
与user786653一样,奇怪的重复模板模式可以解决这个问题
template<typename Visitor, typename Derived>
struct ElementBase : public Base
{
void visit()
{
_e.visit(static_cast<Derived*>(this));
}
private:
Visitor _e;
};
// Atoms.
template<typename Visitor>
struct ElementA : public ElementBase<Visitor, ElementA<Visitor> >
{
ElementA() : a(5) {}
int a;
};
// Visitors.
struct VisitorA
{
void visit(ElementA<VisitorA> *a)
{
cout << a->a << endl;
}
};