need a virtual template member workaround
我需要编写一个实现访问者设计模式的程序。问题是,基本访问者类是一个模板类。这意味着baseVisited::accept()将模板类作为参数,因为它使用"this",并且我需要"this"指向对象的正确运行时实例,所以它也需要是虚拟的。我想知道有没有办法解决这个问题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | template <typename T> class BaseVisitor { public: BaseVisitor(); T visit(BaseVisited *visited); virtual ~BaseVisitor(); } class BaseVisited { BaseVisited(); template <typename T> virtual void accept(BaseVisitor<T> *visitor) { visitor->visit(this); }; // problem virtual ~BaseVisited(); } |
你应该做的是把地下访客分开。
1 2 3 4 5 6 7 8 9 10 11 12 13 | class BaseVisited; class BaseVisitorInternal { public: virtual void visit(BaseVisited*) = 0; virtual ~BaseVisitorInternal() {} }; class BaseVisited { BaseVisited(); virtual void accept(BaseVisitorInternal* visitor) { visitor->visit(this); } }; template<typename T> class BaseVisitor : public BaseVisitorInternal { void visit(BaseVisited* visited); }; |
如果您还需要对baseVisited的派生类进行模板化,并将其正确的类型/重载传递给您,那么您就正式死了。
不能声明/定义模板化虚拟函数。原因是,当编译器看到基类定义时,必须知道虚拟调度机制,但模板是按需编译的。
对于常见的vtable实现,问题是编译器必须为虚拟函数保留的条目数未定义(可以有多少不同类型的实例化?)和他们的顺序一样。如果您声明类:
1 2 3 4 5 | class base { public: virtual void foo(); virtual int bar(); }; |
编译器可以在vtable中为指向vtable中
我想出了一些与Deadmg稍有不同的东西:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | class BaseVisited; class IVisitor { public: virtual void visit(BaseVisited *visited) = 0; virtual ~IVisitor(); }; template <typename T> class BaseVisitor : public IVisitor { public: BaseVisitor(); virtual void visit(BaseVisited *visited); virtual ~BaseVisitor(); virtual T result(); }; class BaseVisited { public: BaseVisited(); virtual void accept(IVisitor *visitor) { visitor->visit(this); }; virtual ~BaseVisited(); }; |
我的有一个额外的