这个班级是如何构建的?

时间:2013-09-19 13:58:07

标签: c++

我很困惑该类如何通过将自身作为模板参数传递而继承自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;
};

2 个答案:

答案 0 :(得分:6)

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

您可以在wikipedia

上阅读更多内容

答案 1 :(得分: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提供的基本定义。您的类层次结构的调用者也可以利用这种静态多态性。

这是一个short example,可以帮助您更好地直观了解正在发生的事情:

#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类   在代码中。 “:”运算符是否用于继承之外的其他事物   来自一个班级?

RewriteMyRecursiveASTVisitor类的成员变量,是对Rewriter类型对象的引用。 :运算符用于构造函数的定义以表示member initializer list。在这种情况下,我们只需使用传入的参数Rewrite初始化R变量。需要明确的是,MyRecursiveASTVisitor(Rewriter &R) : Rewrite(R) { }是您的班级MyRecursiveASTVisitor的构造函数定义,类定义。