2012-03-15 15 views
13

私はこのようないくつかのイベントがありフォース呼び出し、基本クラスの仮想関数

class Granpa // this would not be changed, as its in a dll and not written by me 
{ 
public: 

    virtual void onLoad(){} 

} 

class Father :public Granpa // my modification on Granpa 
{ 
public: 

    virtual void onLoad() 
    { 
     // do important stuff 
    } 

} 

class Child :public Father// client will derive Father 
{ 

    virtual void onLoad() 
    { 
     // Father::onLoad(); // i'm trying do this without client explicitly writing the call 

     // clients code 
    } 
} 

実際父::のonLoad()を記述せずに呼び出すのonLoadを強制する方法はありますか?

ハックソリューションは歓迎されている:)

+4

なぜこれが問題なのか分かりません。あなたは明示的に何かをしたいので、コード内で明示的に言う必要があります... –

+2

明示的に起こりたいことをするためにコード行を追加しないのはちょっと怠惰でしょうか? –

+0

同じ問題がMFCハンドラで解決されていないので(CMyDialog :: OnInitDialog()からCDialog :: OnInitDialog()を明示的に呼び出す必要があります)。 – Mikhail

答えて

24

私が正しく理解していればオーバーライドされた関数が呼び出されるたび、基本クラスの実装は常に最初に呼び出される必要があるように、あなたがそれをしたいです。この場合、template patternを調査することができます。次のようなものがあります:

class Base 
{ 
public: 
    void foo() { 
     baseStuff(); 
     derivedStuff(); 
    } 

protected: 
    virtual void derivedStuff() = 0; 
private: 
    void baseStuff() { ... } 
}; 

class Derived : public Base { 
protected: 
    virtual void derivedStuff() { 
     // This will always get called after baseStuff() 
     ... 
    } 
}; 
+2

非仮想インターフェイスとも呼ばれます(私は常にテンプレートメソッドパターンとして知られていますが)。 –

+0

derivedStuffは両方のクラスでプライベートにすることもできます。 – Dan

+2

良い説明はこちらhttp://www.gotw.ca/publications/mill18.htm – pmr

4

上記のとおりですが、あなたのケースに適用されます。

class Father :public Granpa // my modification on Granpa 
{ 

public: 

    virtual void onLoad() 
    { 
     // do important stuff 
     onLoadHandler(); 
    } 
    virtual void onLoadHandler()=0; 
} 

class Child :public Father// client will derive Father 
{ 

    virtual void onLoadHandler() 
    { 

     // clients code 
    } 
} 

のC++は何の最終キーワードを持っていないとGranpaのonLoadが仮想そのものであるので、何もオンロードを無効にするために子供を防ぐことはできません。

+4

幸いにも、C++ 11には最終的なキーワードがあります。 – juanchopanza

2

まあ、これを行うための広く知られた、認識された方法はありません。存在していれば、イベントとシグナルを使用しているGUIライブラリがおそらくそれを実装していたでしょう。しかし、あなたの問題に対する他の解決策があります。

あなたは、boost.Signals、sigslot、または自分で作ったものを使ってシグナルイベント接続を実装できます。 GTK +が行うよう:

g_signal_connect(my_wdg, "expose-event", G_CALLBACK(my_func), NULL); 

gboolean my_func(...) 
{ 
    // do stuff 
    return FALSE; /* this tells the event handler to also call the base class's slot */ 
} 

を以下C-中心のように、これは、これらの線に沿って実装することができます

/* In Granpa */ 
/* typedef a functor as 'DerivedEventHandler' or use a boost::function */ 
std::vector<DerivedEventHandler> handlers; 

void connect(DerivedEventHandler event) { handlers.push_back(event); } 

/* in loop */ 
while (! iter = handlers.end()) /* call event */ 

/* In constructor of Father */ 
this->connect(this->OnLoad); 

/* In constructor of Child */ 
this->connect(this->OnLoad); 

/* and so on... in all derived classes */ 
-1

問題のオブジェクトをコピーして小型で安価である場合は、単にベースを呼び出しますつまり、BaseClass(* derived_class_object).method()

+0

おそらくOPが望んでいたものではないでしょう。なぜなら、彼は、このアプローチでもしなければならないbaseClass関数呼び出しを明示的に書くことを避ける方法を尋ねたからです。 – Haatschii

関連する問題