2016-11-21 10 views
2

私はこの優れた訪問者パターンに基づいていくつかのクラスを書いたhere(私の実装は少し異なります)。作品上記C++:テンプレートクラスから派生した仮想純関数をオーバーライド

template<typename... Types> 
class Visitable { 
public: 
    virtual void accept(Visitor<Types...>& visitor) = 0; 
}; 

class MyClass : public Visitable<int, string> 
{ 
    virtual void accept(Visitor<int, string>& visitor) 
    { 
      /*** my code ***/ 
    } 
}; 

このコードが、私はそのようなMyClassを実装したいと思います:

class MyClass : public Visitable<int, string> 
{ 
     template<typename... Types> 
     virtual void accept(Visitor<Types...>& visitor) 
     { 
       /*** my code ***/ 
     } 
}; 
明らか

私は受け入れるメソッドの呼び出しを変更しますが、私はこのエラーを持っている:「は抽象クラスをインスタンス化することはできません」 。なぜこの2番目のケースでは、accept()がオーバーライドされないのですか? MyClassはテンプレート化する必要がありますか?

ありがとうございました。

+0

テンプレートは関数ではないため、基本クラス関数をオーバーライドする関数はありません。 –

答えて

3

はCRTPを使用します。

template<class D, class...Ts> 
struct Visitable_CRTP : public Visitable<Ts...> { 
    virtual void accept(Visitor<Ts...>& visitor) override final { 
    return static_cast<D*>(this)->accept_impl(visitor); 
    } 
}; 
class MyClass : public Visitable_CRTP<MyClass, int, string> 
{ 
    template<typename... Types> 
    void accept_impl(Visitor<Types...>& visitor) // not virtual 
    { 
      /*** my code ***/ 
    } 
}; 

Visitor_CRTPあなたtemplate accept_implvirtual acceptを添付グルーコードを書き込みます。複数のaccept方法を持っているしたい場合は

、我々はこれを行うことができます。このように使用することができます

template<class D, class...Visitables> 
struct PolyVisitable_CRTP {}; 

template<class D, class...V0, class...Vs> 
struct PolyVisitable_CRTP<D, Visitable<V0...>, Vs...> 
    Visitable_CRTP<D, V0...>, 
    PolyVisitable_CRTP<D, Vs...> 
{}; 

class MyClass : 
    public PolyVisitable_CRTP<MyClass, 
    Visitable<int,double>, 
    Visitable<std::string, char, wchar_t>, 
    Visitable<> 
    > 
{ 
    template<typename... Types> 
    void accept_impl(Visitor<Types...>& visitor) 
    { 
      /*** my code ***/ 
    } 
}; 

Visitable拠点のaccept Sのすべての意志accept_implにルーティングしてください。

コードはテストされていないか、コンパイルされていない可能性があります。おそらくtpyosが含まれています。

+0

少なくとも「tpyos」という単語には、タイプミスが含まれています。 –

+0

この優れた答えをありがとう!! – Milleras

0

は実際にあなたがCで

void MyClass::accept<int, string>(Visitor<int, string>& visitor); 

void VisitTable<int, string>::accept(Visitor<int, string>& visitor); 

を実装しよう++、それは同じメソッド名ではありません - 1は、テンプレートの資格を持っており、他ではありません。またtemplatevirtualは方法のために、互換性のない指定子であり、あなたはoverride C++ 11のキーワードは、このような驚きを避けるために役立ちます

class MyClass : ... { 
    ... 
    template<typename... Types> 
    virtual void accept(Visitor<Types...>& visitor); 
}; 

error: templates may not be ‘virtual’ 

のエラーを持っている必要があります。

+0

あなたの発言で私は今私の間違いを理解しています。ありがとうございました。通常は 'override'を使いますが、ここでは忘れてしまいます。 – Milleras

関連する問題