【发布时间】:2012-10-19 00:41:21
【问题描述】:
请注意:这些是描述一般困境的代码 sn-ps。完整的代码确实包括“包含警卫”/#pragma once/whathaveyou。
我正在实现用于遍历 AST 的访问者模式,并想知道 C++ 解决以下问题的方法是什么:
我有 AST.h,它有基本的 AST 节点类声明:
class Node
{
public:
virtual void accept(Visitor* v) {v->visit(this);}
};
以及用于声明、表达式等的所有具体节点子类。
然后我有声明访问者界面的 ASTVisitor.h,大致如下:
class Visitor
{
public:
Visitor() {}
virtual ~Visitor() {}
virtual void visit(StringElement* e) {}
virtual void visit(RealElement* e) {}
virtual void visit(IntegerElement* e) {}
...
问题是,AST.h 需要 ASTVisitor.h 以便接受方法知道访问者对象有访问方法。也就是说,Visitor 和 visit() 都被声明为 virtual void accept(Visitor* v) {v->visit(this);}。但与此同时,ASTVisitor.h 需要 AST.h 以便 Visitor 类知道 Node 的所有具体子类都存在。也就是说,例如,在 virtual void visit(StringElement* e) 中为签名声明 StringElement
但是在 ASTVisitor.h 中包含 ASTVisitor.h 和在 ASTVisitor.h 中包含 AST.h 会导致访问者类没有被 Node 类“看到”,因此,它作为接受参数的类型无效。此外,像 AST.h 中的 class Visitor; 这样的前向声明只能解决方法签名的类型问题,但在方法 v->visit(this) 内部仍然无效,因为前向声明没有说明访问者类的方法。
那么解决这个问题的 C++ 方法是什么?
【问题讨论】: