【问题标题】:need a virtual template member workaround需要一个虚拟模板成员解决方法
【发布时间】:2011-02-25 18:14:54
【问题描述】:

我需要编写一个实现访问者设计模式的程序。问题是基本访问者类是一个模板类。这意味着 BaseVisited::accept() 将模板类作为参数,并且由于它使用“this”并且我需要“this”来指向对象的正确运行时实例,因此它也需要是虚拟的。
我想知道有没有办法解决这个问题。

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();
}

【问题讨论】:

  • 编译器不接受虚函数中的模板。
  • 为什么要将访问者设为模板?你想用这个构造解决什么问题?您想做的事情无法完成,但可能有其他方法可以实现您真正需要的内容。

标签: c++ templates virtual visitor-pattern


【解决方案1】:

你应该做的是分离 BaseVisitor。

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 的派生类进行模板化并传递它们正确的类型/重载来访问,那么您就死定了。

【讨论】:

【解决方案2】:

我想出了一些与 DeadMG 稍有不同的东西:

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();
};

我的有一个额外的result() 成员函数,可让您检索上次访问的结果。

【讨论】:

    【解决方案3】:

    您不能声明/定义模板化的虚函数。原因是编译器看到基类定义时必须知道虚拟调度机制,但模板是按需编译的。

    对于常见的 vtable 实现,问题是编译器必须为虚函数保留的条目数量是未定义的(可以有多少种不同的类型实例化?),它们的顺序也是如此。如果你声明类:

    class base {
    public:
       virtual void foo();
       virtual int bar();
    };
    

    编译器可以在vtable中为指向foobar的指针在vtable中保留两个条目,并且仅通过检查类定义就可以完美地定义vtable。这是模板函数无法实现的。

    【讨论】:

    • 我知道这是不可能的,我也理解为什么,我的问题是寻找一个不涉及模板虚函数的解决方案。不过还是谢谢。
    • @Yurib:你想要一个解决方案,但你还没有说明你的问题——我在对这个问题的评论中要求这样做:你真正想要实现的是什么。您只询问了一个不起作用的潜在解决方案,而不是最初的问题是什么。
    猜你喜欢
    • 1970-01-01
    • 2023-04-10
    • 2012-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-22
    • 2016-09-28
    相关资源
    最近更新 更多