2017-06-30 165 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; 
    } 
}; 

注: A不知道哪個類將從它派生,但是從它派生的任何人,如果派生類中沒有reset()覆蓋,調用A :: reset()應該將派生類對象重置爲其構造的狀態即

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

然而,如果存在被複位()在子類的替代時,調用A ::復位()應調用重寫的復位(),即

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

您可能需要查看[Curiously recurring template pattern(CRTP)](https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern)。 –

+0

我的理解是,這只是C++的默認行爲?我的誤解是什麼?所以如果你需要一個特定於B的重置,寫一個覆蓋。要使用CRTP將知識傳遞給A,同時通過B從CRTP派生出來,然後調用B :: reset聽起來有點神祕:-) – Klaus

+0

@Klaus你如何實現問題1)。在A :: reset()中的評論中? – james

回答

2

如所提到的在我的評論中,它可以通過CRTP, ano繼承療法級別:

// 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函數實現。然後是類似B(和C等)的類,它們從realA繼承而不是A

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 

上面的問題是隻有公共成員函數可以使用。