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

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 に答える