2017-06-30 20 views
0

私はこの下のような何かを達成したいと思います:派生クラスのオブジェクトをリセット

class A { 
public: 
    virtual void reset() { 
    // 1). if there's no override to this function, 
    // then whatever derived from A should get reset 
    // to its constructed state, e.g. if B derives from 
    // A, then *this = B(); 
    // 2). if there is an override to reset in the derived 
    // class, call the reset in the derived class 
    } 
}; 
class B: public A { 
public: 
    B() { std::cout<<"reset B"<<std::endl; } 
    // no override of reset() here 
}; 
class C: public A { 
public: 
    void reset() override { 
     std::cout<<"reset C"<<std::endl; 
    } 
}; 

N.B. Aはから派生するクラスを知りませんが、派生クラスにreset()オーバーライドがない場合は、A :: reset()を呼び出すと派生クラスオブジェクトがその構築された状態にリセットされますリセットのオーバーライドがある場合に述べたように、すなわち

A* a = new B(); 
a->reset(); // -> this equals to *a = B(); 

ただし、()派生クラスでは、呼び出し元::リセット()は、)(すなわち

A* a = new C(); 
a->reset(); // -> this should call C::reset() 
+1

[奇妙に繰り返されるテンプレートパターン(CRTP)](https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern)を参照してください。 –

+0

私の理解は、これは単にC++のデフォルトの動作であるということですか?私の誤解は何ですか?したがって、Bに固有のリセットが必要な場合は、オーバーライドを書きます。 CRTPを使用して知識を取得するにはBからCRTPを介して派生し、次にB :: resetを呼び出して少し奇妙な音を出します:-) – Klaus

+0

@Klausどのように質問1)を達成しますか? A :: reset()内の私のコメントで? – james

答えて

2

をオーバーライドされたリセットを呼び出す必要があります私のコメントでは、CRTP anoの助けを借りて解決することができます相続のTHERレベル:

// The base class is just an abstract interface class 
struct A 
{ 
    virtual void reset() = 0; 
}; 

template<typename T> 
struct realA : public A 
{ 
    void reset() override 
    { 
     *this = T(); 
    } 
} 

class B : public realA<B> 
{ 
    ... whatever you need here... 
}; 

今、あなたは

A* a = new B; 
a->reset(); 

を行うことができますし、一見それをしたいと、それが動作するはずです。

あなたは、必要なインターフェイスを含む基本クラスA(現在抽象クラス)を持っています。次に、テンプレートクラスrealAがあります。これにはAクラスの実装に含まれる実装、特にreset関数の実装が含まれています。次にAの代わりにrealAを継承するB(およびCなど)のクラスがあります。

0

受け入れられた回答以外に、別の方法があります。

A* a = new Derived(); 
if(typeid(&A::reset)==typeid(&Derived::reset))// no override 
{ *a = Derived(); } // instead of calling a1->reset() 
else { a->reset(); } // if there is override 

上記の問題は、パブリックメンバー関数だけが使用できるということです。