0

我很困惑该类如何通过将自身作为模板参数传递来从类 RecursiveASTVisitor 继承。此外,是否在行中写入 Rewrite(R)

MyRecursiveASTVisitor(Rewriter &R) : Rewrite(R) { }

将值 R 赋给变量 Rewrite? 代码中的任何地方都没有定义类 Rewrite。“:”运算符是否用于除了从类继承之外的其他事情?

class MyRecursiveASTVisitor
    : public RecursiveASTVisitor<MyRecursiveASTVisitor>
{

 public:
  MyRecursiveASTVisitor(Rewriter &R) : Rewrite(R) { }
  void InstrumentStmt(Stmt *s);
  bool VisitStmt(Stmt *s);
  bool VisitUnaryOperator(UnaryOperator *e);

  Rewriter &Rewrite;
};
4

2 回答 2

6

它被称为奇怪的重复模板模式。当编译器创建RecursiveASTVisitor<MyRecursiveASTVisitor>它时,它知道布局,MyRecursiveASTVisitor所以一切正常。

您可以在维基百科上阅读更多内容

于 2013-09-19T14:01:46.700 回答
1

正如评论所提到的,这被称为Curiously Recurring Template Pattern。这种模式通常被实现以提供类似于虚函数的机制,但在编译时(静态多态性)。例如,RecursiveASTVistor<T>可能包含执行以下操作的方法:

...
//using T = MyRecursiveASTVisitor; for your specific case
T *concrete_visitor = static_cast<T*>(this);
concrete_visitor->VisitStmt(something);

如果VisitStmt在您的MyRecursiveASTVisitor类中定义,则调用该方法,否则调用由RecursiveASTVistor. 类层次结构之外的调用者也可以利用这种静态多态性。

这是一个简短的示例,可帮助您更好地了解正在发生的事情:

#include <iostream> 

template <class T>
struct Base {
    void foo() {
        T *concrete = static_cast<T*>(this);
        concrete->foo();
    };
    void bar() {std::cout << "Base" << std::endl; }
};

struct Derived : public Base<Derived> {
    void foo() {std::cout << "Derived" << std::endl;}
};

int main() {
    Base<Derived> b;
    b.foo();
    b.bar();
}

输出

Derived
Base

编辑:要回答您的其他问题:

此外,在该行中写入 Rewrite(R) 是否 MyRecursiveASTVisitor(Rewriter &R) : Rewrite(R) { }将值 R 分配给变量 Rewrite?代码中的任何地方都没有定义类 Rewrite。“:”运算符是否用于除了从类继承之外的其他事情?

Rewrite是您的MyRecursiveASTVisitor类的成员变量,并且是对类型对象的引用Rewriter。运算符在构造函数的:定义中用于表示成员初始值设定项列表。在这种情况下,我们只需Rewrite使用传入的参数初始化变量R。需要明确的是,MyRecursiveASTVisitor(Rewriter &R) : Rewrite(R) { }是您的类的构造函数定义MyRecursiveASTVisitor,而不是类定义。


于 2013-09-19T14:15:44.757 回答