2017-03-01 4 views
-1

Ich habe eine Reihe von Beispielen gesehen, wie man einen Funktionszeiger auf ein C++ - Klasse nicht-statisches Element einer spezifischen-Klasse setzt. Allerdings würde ich für solche Zeiger verwenden, die für jede Typklasse funktionieren würden. Um die Idee zu demonstrieren, schrieb ich ein Pseudo-Beispiel:C++ - Funktionszeiger auf eine nicht statische Elementfunktion einer beliebigen Klassenart

class A 
{ 
    public: 
    A(){} //constructor  
    void callMe() { /* do something */ } 
}; 

class B 
{ 
    public: 
    B(){} //constructor  
    void callMe() { /* do something */ } 
}; 


main() 
{ 
    A aa; 
    B bb; 

    //pseudo part: 
    generic_method_pointer_type p; //how to define the type of p? 

    p=HOWTO;//set pointer p to point to A::callMe. How to do? 

    p(aa); //A::callMe on instance aa gets called 

    p=HOWTO;//set pointer p to point to B::callMe. How to do? 

    p(bb); //B::callMe on instance bb gets called 
} 

Sieht dies möglich?

Ich weiß, C++ 11 hat neue Tricks wie Std :: Funktion dafür. Ich habe einige Experimente an der std :: function durchgeführt und fand es zu langsam für eine Echtzeit-App, die auf einem kleinen Mikrocontroller läuft. Aus diesem Grund würde ich direkt hart codierte Zeiger bevorzugen, die minimalen Overhead verursachen würden.

Vielen Dank für Ihren Hinweis!

+0

Haben Sie die Beiträge unter den von Ihnen angegebenen Tags gelesen, insbesondere unter den Member-Function-Pointers? –

+0

Hat ein paar Stunden im Netz gesucht. Wenn Sie einen Link zu einer Antwort kennen, würde ich das schätzen. – TeroK

+1

Was erwarten Sie, wenn Sie 'p = & A :: callMe;' einstellen und dann 'p (bb);'? – aschepler

Antwort

0

Gefunden eine perfekt funktionierende Lösung von mbed Projekt Quellcodes (ihre Funktionszeiger-Klasse):

Arbeitsbeispiel:

A foo; 
FunctionPointer cb; 
cb.attach(&foo,&A::callMe); 
for(i=0;i<100000000;i++) //callback overhead test 
    cb.call(); 

Der Code innerhalb von FunctionPointer ist für mich nicht sehr offensichtlich, wie es funktioniert. Es memcpy einige Daten usw. Irgendwelche Ideen, wenn es vereinfacht werden könnte & schneller gemacht? Es bewirkt, dass immer noch deutlich mehr Aufwand im Vergleich zu einem Fall, in dem Klassentyp festgelegt ist, wie zum Beispiel:

A foo; 
typedef void (A::*MethodPtr)(); 
MethodPtr method = &A::callMe; 
Foo *obj = &foo; 
for(i=0;i<100000000;i++) //callback overhead test 
    (obj->*method)(); 

Das obige Verfahren ist etwa 4x schneller im Vergleich zu Funktionszeigern Methode, wenn callme nur asm enthält („nop“). Einige Benchmarks für x86 & GCC:

  • direkten Aufruf 205 ms
  • die obige Funktionszeiger Beispiel 258 ms
  • Funktionszeiger Beispiel 1049 ms
  • std :: function 3951 ms

Alle Optimierungsideen werden sehr geschätzt!

+0

Wenn Sie 'FPointer' betrachten, können Sie alle' c_callback' ausfiltern, da Sie immer ein Objekt haben und sich alle NULL-Pointer-Checks anvertrauen. Was hier vor sich geht, ist das "alle Art Sicherheit geht aus dem Fenster" Zeug, über das ich oben gesprochen habe. Sie können alles einpacken, was Sie wollen und danach beten Sie, dass es richtig ist, weil der Compiler Ihnen nicht helfen kann. – user4581301

+0

Gefunden, dass MBED Callback-Klasse dieses bisschen effizienter, aber nicht sehr signifikanten Leistungsunterschied macht. Läuft Test in ungefähr 900ms. Das Entfernen der Überprüfung spart auch einige Millisekunden. – TeroK

Verwandte Themen