关于C++:需要一个虚拟模板成员工作

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中foobar的指针保留两个条目,只要检查类定义就可以完全定义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();
};

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