C++ method pointer?

Problem: eine Klasse implementiert mehrere (gleichartige) Methoden, von denen eine bestimmte zur Laufzeit aufgerufen werden soll. Leider sind meine C++ Kenntnisse sehr angestaubt, ich komme nicht drauf wie sich das

Ewas konkreter: Es geht um die Klasse IRrecv aus der Arduino IRremote

innerhalb seiner Klasse erzeugen, vorbesetzen und dann aufrufen. Sowas wie:

In der Bibliothek:

class IRrecv { public: bool decodeNEC(); bool decodeSony(); ... bool() *Decoder; //??? soll auf eine der o.g. Methoden zeigen

initialisieren char read(); //soll intern Decoder aufrufen };

IRecv::read() { if (*Decoder()) //??? soll die Methode aufrufen return results.asc; else return '?'; }

Im Programm:

IRrecv irrecv(IR_PIN); //erzeugt Instanz (Singleton)

void setup() { irrecv.begin(&decodeNEC); //??? soll den Pointer initialisieren }

void loop() { if (irrecv.available()) { char data = irrecv.read(); ... } }

Da die Methode nur innerhalb der (selben) Instanz aufgerufen werden

TIA DoDi

Reply to
Hans-Peter Diettrich
Loading thread data ...

Hans-Peter Diettrich schrieb:

Dekoder dann in davon erbenden Klassen zu implementieren.

  1. Christian

--
Christian Zietz  -  CHZ-Soft  -  czietz (at) gmx.net 
WWW: http://www.chzsoft.de/ 
PGP/GnuPG-Key-ID: 0x52CB97F66DA025CA / 0x6DA025CA
Reply to
Christian Zietz

Christian Zietz schrieb:

Sowas dachte ich mir schon ;-)

Verweis auf die Arduino Bibliothek.

Bibliothek auf. Das riecht dann irgendwie nach einem Template?

direkt aufrufen.

Da war ich schon, hilft mir aber nicht bei allen Details :-(

DoDi

Reply to
Hans-Peter Diettrich

Am 09.03.2016 um 18:14 schrieb Hans-Peter Diettrich:

Um Memberfunktionen aufzurufen brauchst Du den Zeiger auf das Objekt.

Wieviel verschiedene Dekoder gibt es denn? Entweder Du baust Dir ein Interface, und erzeugst Dir passende Objekte je nachdem was Du brauchst, oder Du erledigst das einfach mit ner if-Abfrage, oder mit einem switch case Block.

begin(IRecv::DecodeNEC);

IRecv::read() { if (decoder==DecoderNEC) return decodeNEC; else return decodeSony(); }

Reply to
Thorsten Böttcher

Christian Zietz schrieb:

In den vorhandenen Bibliotheken gibt es eine universelle decode()

virtuellen Methoden nicht funktionieren. Die habe ich dann schon mal in

einer unbekannten Fernbedienung) weiterhin verwendet werden kann. Das

Speicher) soll unbedingt wegfallen, wenn man nur von einer bestimmten

Hinweis dankbar :-)

DoDi

Reply to
Hans-Peter Diettrich

Hans-Peter Diettrich schrieb:

Im Quellcode vielleicht. Compiliert kommt ziemlich genau das heraus, was

abgeleitete Klasse hat eine vtable mit einem Pointer auf ihre decode-Methode.

AbstractDecoder* decoder = AbstractDecoder::createDecoder(x); decodeddata = decoder->decode(data);

Je nach Wert von 'x' wird 'decoder' nun zur Laufzeit eine Instanz von SonyDecoder, NECDecoder usw. Trotzdem ruft decoder.decode() immer die passende decode-Methode (und nicht etwa die in AbstractDecoder) auf.

hintippen, aber in d.s.e ist das doch arg off-topic.

Christian

--
Christian Zietz  -  CHZ-Soft  -  czietz (at) gmx.net 
WWW: http://www.chzsoft.de/ 
PGP/GnuPG-Key-ID: 0x52CB97F66DA025CA / 0x6DA025CA
Reply to
Christian Zietz

Deshalb wollte ich ja die Methode innerhalb des Objekts aufrufen, dann ist die Instanz ja bereits bekannt (this).

haben noch viel weniger Ahnung von C++ als ich ;-)

nicht (mehr) aus :-(

DoDi

Reply to
Hans-Peter Diettrich

Christian Zietz schrieb:

(siehe andere Mail).

verzichten, ich hatte auch schon an einen Aufruf wie

gedacht. Aber leider liegen manche Parameter in der Instanz der Klasse,

Bibliotheken beibehalten.

ja unbedingt C oder C++ sein :-(

Zugegeben, in dieser Gruppe findet sich bereits mehr off-topic als

DoDi

Reply to
Hans-Peter Diettrich

Am 09.03.2016 um 20:11 schrieb Hans-Peter Diettrich:

Dann ein Interface, bzw. abstrakte Klasse, da es in C++ keine Interfaces gibt, und dann das passende Objekt erzeugen. Hat Christian bereits geschrieben.

Nein, dazu braucht man keine Templates.

Oder willst Du vor dem Kompilieren entscheiden welcher Dekoder benutzt wird?

MfG

Reply to
Thorsten Böttcher

Hans-Peter Diettrich schrieb:

Den Grund habe ich allerdings nicht verstanden. Auf alle Decoder zugreifen kannst Du mit virtuellen Methoden doch ebenso. Aber egal, dann

Dann halt als Makro, wobei eine Basisklasse und virtuelle Methoden

verwendete Decoder aussortieren.

#define GET_DECODER(x) (new x##Decoder)

AbstractDecoder* decoder = GET_DECODER(Sony); decoder->decode(data);

Christian

--
Christian Zietz  -  CHZ-Soft  -  czietz (at) gmx.net 
WWW: http://www.chzsoft.de/ 
PGP/GnuPG-Key-ID: 0x52CB97F66DA025CA / 0x6DA025CA
Reply to
Christian Zietz

Hans-Peter Diettrich schrieb:

Nur mal eine allgemeine Anmerkung:

Pascal. VMT, abstrakte und virtuelle Methoden, Klassendeklarationen,

Marc

--
Rot ist negativ, blau ist positiv.
Reply to
Marc Santhoff

Ja, den Rest gibt es ja schon.

DoDi

Reply to
Hans-Peter Diettrich

Marc Santhoff schrieb:

DoDi

Reply to
Hans-Peter Diettrich

Hans-Peter Diettrich schrieb:

In der schon geposteten FAQ beschrieben.

Christian

-- Christian Zietz - CHZ-Soft - czietz (at) gmx.net WWW:

formatting link
PGP/GnuPG-Key-ID: 0x52CB97F66DA025CA / 0x6DA025CA

Reply to
Christian Zietz

Hans-Peter Diettrich schrieb:

Zu Pointer und Funktionen:

formatting link

formatting link

Mein PDF hatte zwar eine total verfusselte Seitennummerierung, war aber

Marc

Reply to
Marc Santhoff

Am 09.03.2016 um 22:31 schrieb Hans-Peter Diettrich:

eher verwirrt.

MfG

Reply to
Thorsten Böttcher

Ein Singleton kann eigentlich komplett statisch sein, so dass Du die einfacheren C-Funktionspointer verwenden kannst, indem Du die Methoden

class IRrecv;

typedef bool (foo_decode)(IRrecv* pThis);

class IRrecv { public: static bool decodeNEC(IRrecv* pThis); static bool decodeSony(IRrecv* pThis); char read(foo_decode pFoo); //soll intern Decoder aufrufen };

char IRrecv::read(foo_decode pFoo) { if (pFoo(this)) //??? soll die Methode aufrufen return 'r'; else return '?'; }

int main() { IRrecv irrecv; irrecv.read(IRrecv::decodeNEC);

dem sich die Funktionen als Objekt handhaben lassen:

struct i_decode { // Definition des Interface virtual ~i_decode() {} // verhindert Compilerwarnung virtual bool decode()= 0; // Deklaration Funktionsaufruf };

struct f_decode_NEC: public i_decode { // Definition eines Dekoders, beachte Vererbung vom Interface virtual ~f_decode_NEC() {} // verhindert Compilerwarnung virtual bool decode() { return true; } // Definition Funktion };

struct f_decode_Ed: public i_decode { // Definition noch eines Dekoders virtual ~f_decode_Ed() {} // verhindert Compilerwarnung virtual bool decode() { return false; } };

i_decode* pFoo= new f_decode_NEC; // Funktionsobjekt anlegen if (pFoo->decode()) do_anything(); // benutzt decode_NEC

oder statisch:

f_decode_NEC DNC; // Funktionsobjekt anlegen i_decode* pFoo= &DNC; // Dem Zeiger zuweisen

Reply to
Edzard Egberts

Moin,

Hans-Peter Diettrich schrieb:

Ich hab das mal so geschrieben, wie Du es vermutlich haben willst,

//------------------------- class IRrecv { public: bool decodeNEC(); bool decodeSony(); //... bool (IRrecv::*Decoder)() ; // Member Function Pointer

void begin( bool (IRrecv::*which)() ); char read(); //soll intern Decoder aufrufen };

char IRrecv::read() { if ( (this->*Decoder)() ) // soll die Methode aufrufen return '!'; else return '?'; }

IRrecv irrecv; //erzeugt Instanz (Singleton)

void setup() { //MemFunc Pointer initialisieren irrecv.begin( &IRrecv::decodeNEC ); }

Konstrukte in C++ auch, z.B. templates.

- Heinz

Reply to
Heinz Saathoff

dann noch die Klasse selbst. Das Ergebnis habe ich momentan bereits in

auch die Elemente der Klasse enthalten. [...]

sollte ich wohl noch Makros definieren.

Beibehaltung der Klasse entschieden, mit den Standard-Methoden begin(), available() und read(), die jeder Arduino Programmierer von den anderen Stream-Klassen gewohnt ist.

Speicherbedarf (zumindest bei den VMT).

DoDi

Reply to
Hans-Peter Diettrich

Heinz Saathoff schrieb:

[...] Danke, das ist genau die Antwort, die ich erwartet habe :-)

Jetzt komme ich wohl nicht umhin, Dich im Header der Bibliothek als

DoDi

Reply to
Hans-Peter Diettrich

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.