22

ビジター デザイン パターンを実装するプログラムを作成する必要があります。問題は、基本ビジター クラスがテンプレート クラスであることです。これは、BaseVisited::accept() がテンプレート クラスをパラメータとして取り、'this' を使用し、'this' がオブジェクトの正しい実行時インスタンスを指す必要があるため、仮想化する必要があることを意味します。
この問題を回避する方法があれば知りたいです。

template <typename T>
class BaseVisitor {
  public:
    BaseVisitor();
    T visit(BaseVisited *visited);
    virtual ~BaseVisitor();
}


class BaseVisited {
  BaseVisited();
  template <typename T>
    virtual void accept(BaseVisitor<T> *visitor) { visitor->visit(this); }; // problem
  virtual ~BaseVisited();
}
4

3 に答える 3

17

あなたがすべきことは、BaseVisitor を分離することです。

class BaseVisited;
class BaseVisitorInternal {
public:
    virtual void visit(BaseVisited*) = 0;
    virtual ~BaseVisitorInternal() {}
};
class BaseVisited {
    BaseVisited();
    virtual void accept(BaseVisitorInternal* visitor) { visitor->visit(this); }
};
template<typename T> class BaseVisitor : public BaseVisitorInternal {
    void visit(BaseVisited* visited);
};

BaseVisited の派生クラスもテンプレート化する必要があり、正しい型/オーバーロードを渡してアクセスする必要がある場合は、正式に死んでいます。

于 2010-05-30T19:00:18.183 に答える
4

私は DeadMG とは少し違うものを思いつきました:

class BaseVisited;

class IVisitor {
  public:
    virtual void visit(BaseVisited *visited) = 0;
    virtual ~IVisitor();
};

template <typename T>
class BaseVisitor : public IVisitor {
  public:
    BaseVisitor();
    virtual void visit(BaseVisited *visited);
    virtual ~BaseVisitor();
    virtual T result();
};


class BaseVisited {
  public:
    BaseVisited();
    virtual void accept(IVisitor *visitor) { visitor->visit(this); };
    virtual ~BaseVisited();
};

result()私のものには、最後の訪問の結果を取得できる追加のメンバー関数があります。

于 2010-05-30T19:05:50.897 に答える
3

テンプレート化された仮想関数を宣言/定義することはできません。その理由は、コンパイラが基本クラス定義を確認するときに仮想ディスパッチメカニズムを認識している必要がありますが、テンプレートはオンデマンドでコンパイルされるためです。

一般的なvtableの実装では、問題は、コンパイラが仮想関数用に予約する必要のあるエントリの数が未定義であるということです(タイプのさまざまなインスタンス化がいくつあるか)、それらの順序も同様です。クラスを宣言する場合:

class base {
public:
   virtual void foo();
   virtual int bar();
};

コンパイラーは、vtableへのポインターfooおよびbarvtable内のポインター用にvtable内の2つのエントリーを予約でき、vtableは、クラス定義を検査するだけで完全に定義されます。これは、テンプレート化された関数では実現できません。

于 2010-05-30T19:31:05.650 に答える