2016-03-29 12 views
1

私は複数の子クラスを持ち、抽象実行メソッドを提供するテンプレートベースクラスを持っています。子プロセスはこのメソッドをさまざまな方法で実装し、Baseクラスのテールベクタのオブジェクトに実行呼び出しを委譲できます。 オブジェクトをテールに連結するために、Baseクラスはいくつかのメソッド(createChild1、createChild2)を提供します。ここでは、コードです:テンプレート継承階層の循環依存性

base.h

#pragma once 

#include <memory> 
#include <vector> 

template<typename T> 
class Child1; 

template<typename T> 
class Child2; 

template<typename T> 
class Base { 
public: 
    std::vector<std::unique_ptr<Base<T>>> tail; 

    virtual void execute(const T &t) = 0; 

    Base<T> &createChild1() { 
     auto child = std::make_unique<Child1<T>>(); 
     tail.push_back(std::move(child)); 
     return *tail.back().get(); 
    } 

    Base<T> &createChild2() { 
     auto child = std::make_unique<Child2<T>>(); 
     tail.push_back(std::move(child)); 
     return *tail.back().get(); 
    } 
}; 

child1.h

#pragma once 

#include "base.h" 

template<typename T> 
class Child1 : public Base<T> { 
public: 
    virtual void execute(const T &t) { 
     // do something with t 
    } 
}; 

child2.h

#pragma once 

#include "base.h" 

template<typename T> 
class Child2 : public Base<T> { 
public: 
    virtual void execute(const T &t) { 
     // do something with t 
     // then delegate to t 
     for (auto &next : tail) { 
      next->execute(t); 
     } 
    } 
}; 

main.cppに

#include <iostream> 

#include "child1.h" 

using namespace std; 

int main(int argc, char **argv) { 
    Child1<int> c; 
    c.createChild2().createChild1(); 
    c.execute(10); 
    return 0; 
} 

コンパイルしようとすると、未定義のテンプレート 'Child2'の暗黙的なインスタンスが生成されます。なぜなら、Baseでは、Child2というテンプレートクラスは前方宣言され、そのボディはその時点では分からないからです。 Child1とChild2の前にBaseを前方に宣言し、BaseにChild1とChild2の定義を含めても、Child2はtailにアクセスできないため、問題は解決しません。 この循環依存をどのように解決できますか? Child1、Child2、Baseのコードは変更できますが、create呼び出しをmainで連鎖させる可能性を保ちたいので、createメソッドはBaseクラスで宣言する必要があります。

+0

'と 'ベース&createChild2()' base.tppという名前のファイルにしてからということにする。そのためだけchild2.hを変更する必要がありますあなたがメインに含む最後のファイル。私はちょうどコメントとしてそれを提案しているので、ちょっとハッキーです。 – NathanOliver

+0

実際にこのテールをthis-> tailに置き換えると、ジョブが実行されます。とにかくありがとうございました :) – freakout

答えて

0

この解決方法では、テールへのアクセスの前にthis->があります。 )あなたがベース &createChild1( `の定義を移動することができるはず

#pragma once 

#include "base.h" 

template<typename T> 
class Child2 : public Base<T> { 
public: 
    virtual void execute(const T &t) { 
     // do something with t 
     // then delegate to t 
     for (auto &next : this->tail) { 
      next->execute(t); 
     } 
    } 
};