请注意:这些是描述一般困境的代码片段。完整的代码确实包括“包括警卫”/#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 的所有具体子类都存在。也就是说,例如,StringElement 被声明为virtual void visit(StringElement* e)
但是,在 AST.h 中包含 ASTVisitor.h 和在 ASTVisitor.h 中包含 AST.h 会导致访问者类没有被 Node 类“看到”,因此,它作为接受参数的类型无效。此外,像class Visitor;
在 AST.h 中那样进行前向声明只能解决方法签名的类型问题,但在方法内部v->visit(this)
仍然无效,因为前向声明没有说明访问者类的方法。
那么解决这个问题的 C++ 方法是什么?