2009-06-26 9 views
3

Ich fragte mich, ob ich Pre/Post Funktionsaufruf in C++ irgendwie tun könnte. Ich habe eine Wrapper-Klasse mit vielen Funktionen, und nach jedem Wrapper-Funktionsaufruf sollte ich eine andere immer die gleiche Funktion aufrufen.Pre/Post Funktionsaufruf Implementierung

So möchte ich nicht, dass postFunction setzen() so zu jedem einzelnen der Funktionen aufrufen:

class Foo { 
    f1(); 
    f2(); 
    f3(); 
    . 
    . 
    . 
    fn(); 
} 

void Foo::f1() { 
    ::f1(); 
    postFunction(); 
} 

void Foo::f2() { 
    ::f2(); 
    postFunction(); 
} 

etc. 

Stattdessen möchte ich, dass postFunction Anruf automatisch kommen, wenn ich einige Mitgliedfunktion Foo aufrufen. Ist es möglich? Es wäre Wartung helfen ..

+0

Das klingt wie ein Betrogener vor ein oder zwei Monaten, aber ich kann es nicht finden. Ich denke, es gab einige ziemlich gute Antworten. – crashmstr

+0

[Wrapping C++ Member Funktionsaufrufe] (http://www.stroustrup.com/wrapper.pdf) –

Antwort

11

ein Fall für RAII Könnte sein, um sicherzustellen! Dun-dun-dunnn!

struct f1 { 
    f1(Foo& foo) : foo(foo) {} // pre-function, if you need it 
    void operator()(){} // main function 
    ~f1() {} // post-function 

private: 
    Foo& foo; 
} 

Dann müssen Sie nur sicherstellen, dass jedes Mal ausführen möchten Sie eine neue temporäre f1-Objekt erstellen um die Funktion aufzurufen. Die Wiederverwendung bedeutet natürlich, dass die Pre/Post-Funktionen nicht jedes Mal aufgerufen werden.

Könnte sogar wickeln Sie es wie folgt aus:

void call_f1(Foo& foo) { 
    f1(foo)(); // calls constructor (pre), operator() (the function itself) and destructor (post) 
} 

Sie könnten ein wenig mit anderen Möglichkeiten experimentieren sie zu strukturieren, aber im Allgemeinen finden Sie, wenn Sie nicht Konstrukteuren/Destruktoren bekommen, die schweres Heben zu tun für Sie.

Roman M Ansatz könnte auch eine gute Idee sein. Schreiben Sie einen generischen Wrapper, der einen Funktor oder Funktionszeiger als Argument verwendet. Auf diese Weise kann es pre/post Funktionen vor und nach dem Aufruf seines Arguments aufrufen

3

wie ein Job-Sounds für Aspect Oriented Programming mit AspectC++

+0

Overkill. Siehe die unten stehende Antwort von jalf. Eine temporäre Variable, deren Konstruktor und Destruktor pre und post ist, ist eine sehr übliche und direkte Methode. –

+1

Konzeptionell würde ich ja sagen, Sie sind nach aspektorientierter Programmierung, aber für einen anderen (und nicht-standardmäßigen) Compiler nur dafür zu gehen könnte übertrieben sein – jalf

5

einen Wrapper implementieren, die einen Funktionszeiger als Argument nehmen, und wird vor \ Post-Funktion vor dem Aufruf der Funktion aufrufen.

Foo::caller (function* fp) { 
    preCall(); 
    fp (...); 
    postCall(); 

} 
2

Wie Richie darauf hingewiesen hat, suchen Sie wahrscheinlich nach Aspect Oriented Programming.

Wenn das nicht für Sie funktioniert, eine andere Option, die Sie haben, ist noch eine andere Wrapper-Klasse zu schreiben. Sagen Sie statt Foo, haben Sie eine Schnittstelle namens IFoo. Anschließend können Sie eine Wrapper-Klasse, schreiben die richtige Pre- und Post-Anrufe verwendet werden

class IFoo { 
public: 
    void Bar(); 
} 

class FooWrapper: public IFoo { 
public: 
    FooWrapper(IFoo* pFoo) { 
    m_pFoo = pFoo; 
    } 
    void Bar() { 
    PreBar(); 
    m_pFoo->Bar(); 
    PostBar(); 
    } 
} 
+0

Wie kann dieser Ansatz im Usecase der Frage funktionieren? Ich meine, du musst immer noch so viele Anrufe auf Pre und Post schreiben wie die Anzahl der Funktionen in Foo. Was wir brauchen, ist die Anrufe nur einmal vor und nach zu schreiben. –

0

Ich denke, die Antwort wurde vom Vater von C++ B.Stroustrup gegeben.

Wrapping C++ Member Function Calls

Dieses Papier eine einfache, allgemein präsentiert und effiziente Lösung für das alte Problem der ‚‚Verpackung‘‘ ruft zu einem Objekt in Paaren von Präfix und Suffix-Code. Die Lösung ist auch non-intrusive, gilt für vorhandene Klassen, ermöglicht die Verwendung mehrerer Präfix/Suffix-Paare und kann in 15 einfachen Zeilen von Standard C++ implementiert werden. Eine robuste Version des Wrappers wird ebenfalls vorgestellt. Der Anspruch der Effizienz wird durch Messung gestützt.