Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > de.sci.electronics > #203890 > unrolled thread

C++ method pointer?

Started byHans-Peter Diettrich <DrDiettrich1@aol.com>
First post2016-03-09 18:14 +0100
Last post2016-03-11 09:14 +0100
Articles 20 on this page of 25 — 6 participants

Back to article view | Back to de.sci.electronics


Contents

  C++ method pointer? Hans-Peter Diettrich <DrDiettrich1@aol.com> - 2016-03-09 18:14 +0100
    Re: C++ method pointer? Christian Zietz <newsgroup.1001@chz.xyz> - 2016-03-09 18:24 +0100
      Re: C++ method pointer? Hans-Peter Diettrich <DrDiettrich1@aol.com> - 2016-03-09 19:43 +0100
        Re: C++ method pointer? Christian Zietz <newsgroup.1001@chz.xyz> - 2016-03-09 20:03 +0100
          Re: C++ method pointer? Hans-Peter Diettrich <DrDiettrich1@aol.com> - 2016-03-09 20:29 +0100
            Re: C++ method pointer? Christian Zietz <newsgroup.1001@chz.xyz> - 2016-03-09 20:47 +0100
      Re: C++ method pointer? Hans-Peter Diettrich <DrDiettrich1@aol.com> - 2016-03-09 19:57 +0100
    Re: C++ method pointer? Thorsten Böttcher <thorsten_nospam@gmx.net> - 2016-03-09 19:49 +0100
      Re: C++ method pointer? Hans-Peter Diettrich <DrDiettrich1@aol.com> - 2016-03-09 20:11 +0100
        Re: C++ method pointer? Thorsten Böttcher <thorsten_nospam@gmx.net> - 2016-03-09 20:35 +0100
          Re: C++ method pointer? Hans-Peter Diettrich <DrDiettrich1@aol.com> - 2016-03-09 22:31 +0100
            Re: C++ method pointer? Thorsten Böttcher <thorsten_nospam@gmx.net> - 2016-03-10 06:45 +0100
              Re: C++ method pointer? Hans-Peter Diettrich <DrDiettrich1@aol.com> - 2016-03-10 16:59 +0100
    Re: C++ method pointer? Marc Santhoff <m.santhoff@t-online.de> - 2016-03-09 20:47 +0100
      Re: C++ method pointer? Hans-Peter Diettrich <DrDiettrich1@aol.com> - 2016-03-09 22:33 +0100
        Re: C++ method pointer? Christian Zietz <newsgroup.1001@chz.xyz> - 2016-03-09 23:11 +0100
        Re: C++ method pointer? Marc Santhoff <m.santhoff@t-online.de> - 2016-03-10 01:29 +0100
          Re: C++ method pointer? Hans-Peter Diettrich <DrDiettrich1@aol.com> - 2016-03-11 13:24 +0100
    Re: C++ method pointer? Edzard Egberts <ed_09@tantec.de> - 2016-03-10 08:51 +0100
      Re: C++ method pointer? Hans-Peter Diettrich <DrDiettrich1@aol.com> - 2016-03-10 16:33 +0100
    Re: C++ method pointer? Heinz Saathoff <newshsaat@arcor.de> - 2016-03-10 09:14 +0100
      Re: C++ method pointer? Hans-Peter Diettrich <DrDiettrich1@aol.com> - 2016-03-10 16:42 +0100
        Re: C++ method pointer? Edzard Egberts <ed_09@tantec.de> - 2016-03-10 19:12 +0100
          Re: C++ method pointer? Edzard Egberts <ed_09@tantec.de> - 2016-03-11 08:04 +0100
          Re: C++ method pointer? Heinz Saathoff <newshsaat@arcor.de> - 2016-03-11 09:14 +0100

Page 1 of 2  [1] 2  Next page →


#203890 — C++ method pointer?

FromHans-Peter Diettrich <DrDiettrich1@aol.com>
Date2016-03-09 18:14 +0100
SubjectC++ method pointer?
Message-ID<dkb40lFph51U1@mid.individual.net>
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 
mit einem Methoden-Pointer erledigen läßt :-(

Ewas konkreter: Es geht um die Klasse IRrecv aus der Arduino IRremote 
Bibliothek. Sie enthält Dekodierer für verschiedene Protokolle, z.B. 
decodeNEC(), decodeSony(), die ich schon von allem überflüssigen Ballast 
befreit habe. Nun möchte ich einen Pointer auf eine dieser Methoden 
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
     void begin(???); //soll Decoder mit dem übergebenen Parameter 
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 
soll, könnte ein einfacher Pointer ausreichen?

Wie müssen die oben markierten Stellen genau aussehen?

TIA
DoDi

[toc] | [next] | [standalone]


#203892

FromChristian Zietz <newsgroup.1001@chz.xyz>
Date2016-03-09 18:24 +0100
Message-ID<dkb4itFpm0sU1@mid.individual.net>
In reply to#203890
Hans-Peter Diettrich schrieb:

> 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 
> mit einem Methoden-Pointer erledigen läßt :-(

1. Eine C++-Newsgroup existiert. Dort wäre Deine Frage sogar on-topic.
2. Der lehrbuchhafte Weg in C++ wäre, die decode-Methode als virtuelle
Methode in einer Basisklasse zu deklarieren und die tatsächlichen
Dekoder dann in davon erbenden Klassen zu implementieren.
3. <https://isocpp.org/wiki/faq/pointers-to-members>

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

[toc] | [prev] | [next] | [standalone]


#203897

FromHans-Peter Diettrich <DrDiettrich1@aol.com>
Date2016-03-09 19:43 +0100
Message-ID<dkb97bFqtk3U1@mid.individual.net>
In reply to#203892
Christian Zietz schrieb:
> Hans-Peter Diettrich schrieb:
> 
>> 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 
>> mit einem Methoden-Pointer erledigen läßt :-(
> 
> 1. Eine C++-Newsgroup existiert. Dort wäre Deine Frage sogar on-topic.

Sowas dachte ich mir schon ;-)
Über die Syntax hinaus geht es mir auch um den Speicherbedarf, und die 
beste Variante für den Einsatz auf einem µC. Deshalb auch der längliche 
Verweis auf die Arduino Bibliothek.

> 2. Der lehrbuchhafte Weg in C++ wäre, die decode-Methode als virtuelle
> Methode in einer Basisklasse zu deklarieren und die tatsächlichen
> Dekoder dann in davon erbenden Klassen zu implementieren.

Ich dachte auch schon an eine Klasse pro Protokoll, nur bläht das die 
Bibliothek auf. Das riecht dann irgendwie nach einem Template?

Virtuell scheint mir auch überflüssig, denn wenn man ein Objekt der 
abgeleiteten Klasse erzeugen muß, dann kann man dessen Methoden auch 
direkt aufrufen.

> 3. <https://isocpp.org/wiki/faq/pointers-to-members>

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

Danke für die Hilfe :-)

DoDi

[toc] | [prev] | [next] | [standalone]


#203900

FromChristian Zietz <newsgroup.1001@chz.xyz>
Date2016-03-09 20:03 +0100
Message-ID<dkbacvFr7hsU1@mid.individual.net>
In reply to#203897
Hans-Peter Diettrich schrieb:

> Ich dachte auch schon an eine Klasse pro Protokoll, nur bläht das die 
> Bibliothek auf.

Im Quellcode vielleicht. Compiliert kommt ziemlich genau das heraus, was
Du mit Deinen händischen Methodenpointern auch machen willst. Jede
abgeleitete Klasse hat eine vtable mit einem Pointer auf ihre
decode-Methode.

> Virtuell scheint mir auch überflüssig, denn wenn man ein Objekt der 
> abgeleiteten Klasse erzeugen muß, dann kann man dessen Methoden auch 
> direkt aufrufen.

Eben nicht. Du könntest z.B. sowas haben:

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.
Genau *dafür* brauchst Du virtuelle Methoden. => C++-Lehrbuch lesen.

Wäre das hier eine C++-NG, würde ich Dir eben ein komplettes Beispiel
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

[toc] | [prev] | [next] | [standalone]


#203907

FromHans-Peter Diettrich <DrDiettrich1@aol.com>
Date2016-03-09 20:29 +0100
Message-ID<dkbbsfFrl7lU1@mid.individual.net>
In reply to#203900
Christian Zietz schrieb:
> Hans-Peter Diettrich schrieb:
> 
>> Ich dachte auch schon an eine Klasse pro Protokoll, nur bläht das die 
>> Bibliothek auf.
> 
> Im Quellcode vielleicht. Compiliert kommt ziemlich genau das heraus, was
> Du mit Deinen händischen Methodenpointern auch machen willst. Jede
> abgeleitete Klasse hat eine vtable mit einem Pointer auf ihre
> decode-Methode.
> 
>> Virtuell scheint mir auch überflüssig, denn wenn man ein Objekt der 
>> abgeleiteten Klasse erzeugen muß, dann kann man dessen Methoden auch 
>> direkt aufrufen.
> 
> Eben nicht. Du könntest z.B. sowas haben:
> 
> AbstractDecoder* decoder = AbstractDecoder::createDecoder(x);
> decodeddata = decoder->decode(data);

Mir ist schon eingefallen, warum virtuelle Methoden unerwünscht sind 
(siehe andere Mail).

Eigentlich könnte man hier auf Objekte (immer Singletons) ganz 
verzichten, ich hatte auch schon an einen Aufruf wie
   if (decodeNEC(ErgebnisVar)) ... //liefert Wert in ErgebnisVar zurück
gedacht. Aber leider liegen manche Parameter in der Instanz der Klasse, 
und es wäre auch aufwendiger, neue Decoder einzufügen. Deshalb möchte 
ich auch eine weitgehende Kompatibilität mit den vorhandenen 
Bibliotheken beibehalten.

> 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.
> Genau *dafür* brauchst Du virtuelle Methoden. => C++-Lehrbuch lesen.

Wie gesagt, dynamische Erzeugung ist überflüssig und auf einem 
schmalbrüstigen µC auch unerwünscht.

Meine C++ "Lehrbücher" (Borland C++) sind leider ziemlich alt, und 
beantworten meine Fragen auch nicht. Mir wäre eine andere Sprache auch 
lieber, OPL oder Ada, aber für die Verwendung in der Arduino IDE muß es 
ja unbedingt C oder C++ sein :-(

> Wäre das hier eine C++-NG, würde ich Dir eben ein komplettes Beispiel
> hintippen, aber in d.s.e ist das doch arg off-topic.

Zugegeben, in dieser Gruppe findet sich bereits mehr off-topic als 
Antworten auf Fragen, aber kurze konkrete Antworten würden helfen, 
weiteren Traffic überflüssig zu machen :-]

DoDi

[toc] | [prev] | [next] | [standalone]


#203911

FromChristian Zietz <newsgroup.1001@chz.xyz>
Date2016-03-09 20:47 +0100
Message-ID<dkbcu9Fru91U1@mid.individual.net>
In reply to#203907
Hans-Peter Diettrich schrieb:

> Mir ist schon eingefallen, warum virtuelle Methoden unerwünscht sind 
> (siehe andere Mail).

Den Grund habe ich allerdings nicht verstanden. Auf alle Decoder
zugreifen kannst Du mit virtuellen Methoden doch ebenso. Aber egal, dann
müh Dich eben weiter mit Pointern auf Methoden ab...

> Wie gesagt, dynamische Erzeugung ist überflüssig und auf einem 
> schmalbrüstigen µC auch unerwünscht.

Dann halt als Makro, wobei eine Basisklasse und virtuelle Methoden
weiterhin erforderlich sind. Dann kann der Linker wie gewünscht nicht
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

[toc] | [prev] | [next] | [standalone]


#203899

FromHans-Peter Diettrich <DrDiettrich1@aol.com>
Date2016-03-09 19:57 +0100
Message-ID<dkba1jFr4knU1@mid.individual.net>
In reply to#203892
Christian Zietz schrieb:

> 2. Der lehrbuchhafte Weg in C++ wäre, die decode-Methode als virtuelle
> Methode in einer Basisklasse zu deklarieren und die tatsächlichen
> Dekoder dann in davon erbenden Klassen zu implementieren.

In den vorhandenen Bibliotheken gibt es eine universelle decode() 
Methode, die alle installierten Decoder durchprobiert - die würde mit 
virtuellen Methoden nicht funktionieren. Die habe ich dann schon mal in 
eine eigene Klasse IRrecvAll gepackt, so daß sie bei Bedarf (Ausspähen 
einer unbekannten Fernbedienung) weiterhin verwendet werden kann. Das 
erfordert dann, daß diese Methode Zugriff auf alle Decoder hat, und 
diese dann natürlich ins Programm einbindet. Dieser Overhead (Zeit und 
Speicher) soll unbedingt wegfallen, wenn man nur von einer bestimmten 
Fernbedienung empfangen möchte. Die vorhandenen Bibliotheken erfordern 
Eingriffe (#define), wenn man nicht alle Decoder benutzen möchte, und 
das hat dann wieder unschöne Nebeneffekte, die ich vermeiden möchte.

Aber wenn jemand eine einfachere Lösung einfällt, bin ich für jeden 
Hinweis dankbar :-)

DoDi

[toc] | [prev] | [next] | [standalone]


#203898

FromThorsten Böttcher <thorsten_nospam@gmx.net>
Date2016-03-09 19:49 +0100
Message-ID<nbpr73$77j$1@news.albasani.net>
In reply to#203890
Am 09.03.2016 um 18:14 schrieb Hans-Peter Diettrich:
> 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
> mit einem Methoden-Pointer erledigen läßt :-(

Kann man machen, ist aber unschön. Stichwort Funktoren.
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();
}

[toc] | [prev] | [next] | [standalone]


#203902

FromHans-Peter Diettrich <DrDiettrich1@aol.com>
Date2016-03-09 20:11 +0100
Message-ID<dkbar9FrbmbU1@mid.individual.net>
In reply to#203898
Thorsten Böttcher schrieb:
> Am 09.03.2016 um 18:14 schrieb Hans-Peter Diettrich:
>> 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
>> mit einem Methoden-Pointer erledigen läßt :-(
> 
> Kann man machen, ist aber unschön. Stichwort Funktoren.
> Um Memberfunktionen aufzurufen brauchst Du den Zeiger auf das Objekt.

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

> Wieviel verschiedene Dekoder gibt es denn?

Etwa 10, Tendenz steigend. Zudem hätte ich gerne noch eine Möglichkeit, 
die empfangenen Codes über Tabellen in einen einfacheren Datentyp 
umzuwandeln, z.B. '0'-'9' für numerische Tasten. Das sollte aber 
möglichst ohne komplizierte Programmierung gehen, die meisten Benutzer 
haben noch viel weniger Ahnung von C++ als ich ;-)

> Entweder Du baust Dir ein Interface, und erzeugst Dir passende Objekte 
> je nachdem was Du brauchst,

Das riecht für mich nach einem Template, und da kenne ich mich auch 
nicht (mehr) aus :-(

> 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();
> }

Das hat den Nachteil, daß alle angegebenen Decoder ins Programm 
eingebunden werden, und das möchte ich vermeiden. Der Linker ist ja 
schon so clever, daß er unbenutze Methoden wegläßt, man muß nur noch 
vermeiden, daß diese irgendwo in der Bibliothek referenziert werden.

Danke fürs Mitdenken
DoDi

[toc] | [prev] | [next] | [standalone]


#203908

FromThorsten Böttcher <thorsten_nospam@gmx.net>
Date2016-03-09 20:35 +0100
Message-ID<nbpttb$d2q$1@news.albasani.net>
In reply to#203902
Am 09.03.2016 um 20:11 schrieb Hans-Peter Diettrich:
> Thorsten Böttcher schrieb:
>> Am 09.03.2016 um 18:14 schrieb Hans-Peter Diettrich:
>>> 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
>>> mit einem Methoden-Pointer erledigen läßt :-(
>>
>> Kann man machen, ist aber unschön. Stichwort Funktoren.
>> Um Memberfunktionen aufzurufen brauchst Du den Zeiger auf das Objekt.
>
> Deshalb wollte ich ja die Methode innerhalb des Objekts aufrufen, dann
> ist die Instanz ja bereits bekannt (this).

Das stimmt, ändert aber nichts daran dass man ihn braucht.
>
>> Wieviel verschiedene Dekoder gibt es denn?
>
> Etwa 10, Tendenz steigend. Zudem hätte ich gerne noch eine Möglichkeit,

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

Das könnte im prinzip Dein Singleton machen.

>> Entweder Du baust Dir ein Interface, und erzeugst Dir passende Objekte
>> je nachdem was Du brauchst,
>
> Das riecht für mich nach einem Template, und da kenne ich mich auch
> nicht (mehr) aus :-(

Nein, dazu braucht man keine Templates.

>> 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();
>> }
>
> Das hat den Nachteil, daß alle angegebenen Decoder ins Programm
> eingebunden werden, und das möchte ich vermeiden. Der Linker ist ja
> schon so clever, daß er unbenutze Methoden wegläßt, man muß nur noch
> vermeiden, daß diese irgendwo in der Bibliothek referenziert werden.

Wenn die Dekoder zur Laufzeit ausgewählt werden sollen, dann müssen Sie 
zwangsläufig im Programm sein.
Oder willst Du vor dem Kompilieren entscheiden welcher Dekoder benutzt wird?

MfG

[toc] | [prev] | [next] | [standalone]


#203920

FromHans-Peter Diettrich <DrDiettrich1@aol.com>
Date2016-03-09 22:31 +0100
Message-ID<dkbj5oFtl63U1@mid.individual.net>
In reply to#203908
Thorsten Böttcher schrieb:

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

Ja, den Rest gibt es ja schon.

DoDi

[toc] | [prev] | [next] | [standalone]


#203949

FromThorsten Böttcher <thorsten_nospam@gmx.net>
Date2016-03-10 06:45 +0100
Message-ID<nbr1l3$l92$2@news.albasani.net>
In reply to#203920
Am 09.03.2016 um 22:31 schrieb Hans-Peter Diettrich:
> Thorsten Böttcher schrieb:
>
>> Oder willst Du vor dem Kompilieren entscheiden welcher Dekoder benutzt
>> wird?
>
> Ja, den Rest gibt es ja schon.

Dann mach das doch ganz einfach über eine Präprozessoranweisung, anstatt 
so etwas kompliziertes wie eine Methodenpointer, der später alle anderen 
eher verwirrt.

Ich ging davon aus dass Du zur Laufzeit den Dekoder auswählen willst.

MfG

[toc] | [prev] | [next] | [standalone]


#203985

FromHans-Peter Diettrich <DrDiettrich1@aol.com>
Date2016-03-10 16:59 +0100
Message-ID<dkdk21FemhsU3@mid.individual.net>
In reply to#203949
Thorsten Böttcher schrieb:
> Am 09.03.2016 um 22:31 schrieb Hans-Peter Diettrich:
>> Thorsten Böttcher schrieb:
>>
>>> Oder willst Du vor dem Kompilieren entscheiden welcher Dekoder benutzt
>>> wird?
>>
>> Ja, den Rest gibt es ja schon.
> 
> Dann mach das doch ganz einfach über eine Präprozessoranweisung, anstatt 
> so etwas kompliziertes wie eine Methodenpointer, der später alle anderen 
> eher verwirrt.

So wird das in den bisherigen Bibliotheken gemacht, erfordert dann aber 
Eingriffe in die Bibliothek, um die #defines anzupassen. Das hat dann 
den unerwünschten Effekt, daß man zu jedem Projekt eine neue Kopie der 
Bibliothek anlegen muß, da die nach der Änderung eben nur noch für 
diesen einen Fall genutzt werden kann.

Hinzu kommt die Compiler-Magie, die den Programmcode so abändert, daß 
man die #define nicht ins Anwendungsprogramm verlagern kann, und die 
undurchsichtige Auswahl der tatsächlich benutzten Bibliotheks-Variante - 
was müßte da zur Klarstellung noch alles abgeändert werden? Das kann man 
jedenfalls keinem Arduino-Programmierer zumuten :-(

Diese ganzen Einschränkungen sind mir im Laufe der letzten Wochen 
aufgefallen, in denen ich mich mit dieser Bibliothek befaßt habe. Aber 
nun sehe ich endlich den (hoffentlich) richtigen Tunnel am Ende des 
Lichts ;-)

DoDi

[toc] | [prev] | [next] | [standalone]


#203910

FromMarc Santhoff <m.santhoff@t-online.de>
Date2016-03-09 20:47 +0100
Message-ID<20160309204745.5f8e05a5@puma.das.netz>
In reply to#203890
Hans-Peter Diettrich <DrDiettrich1@aol.com> schrieb:

> 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 mit einem Methoden-Pointer erledigen läßt :-(

Nur mal eine allgemeine Anmerkung:

Der ganze Kram funktioniert größtenteils exakt so, wie in Object
Pascal. VMT, abstrakte und virtuelle Methoden, Klassendeklarationen,
etc. Nur, daß eben eine andere Syntax benutzt wird.

Marc

-- 
Rot ist negativ, blau ist positiv.

[toc] | [prev] | [next] | [standalone]


#203921

FromHans-Peter Diettrich <DrDiettrich1@aol.com>
Date2016-03-09 22:33 +0100
Message-ID<dkbj5uFtl63U2@mid.individual.net>
In reply to#203910
Marc Santhoff schrieb:

> Der ganze Kram funktioniert größtenteils exakt so, wie in Object
> Pascal. VMT, abstrakte und virtuelle Methoden, Klassendeklarationen,
> etc. Nur, daß eben eine andere Syntax benutzt wird.

Und genau diese andere Syntax wüßte ich gerne.

DoDi

[toc] | [prev] | [next] | [standalone]


#203927

FromChristian Zietz <newsgroup.1001@chz.xyz>
Date2016-03-09 23:11 +0100
Message-ID<dkblc7Fu616U1@mid.individual.net>
In reply to#203921
Hans-Peter Diettrich schrieb:

> Und genau diese andere Syntax wüßte ich gerne.

In der schon geposteten FAQ beschrieben.

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

[toc] | [prev] | [next] | [standalone]


#203944

FromMarc Santhoff <m.santhoff@t-online.de>
Date2016-03-10 01:29 +0100
Message-ID<20160310012927.5aca068e@puma.das.netz>
In reply to#203921
Hans-Peter Diettrich <DrDiettrich1@aol.com> schrieb:

> Marc Santhoff schrieb:
> 
> > Der ganze Kram funktioniert größtenteils exakt so, wie in Object
> > Pascal. VMT, abstrakte und virtuelle Methoden, Klassendeklarationen,
> > etc. Nur, daß eben eine andere Syntax benutzt wird.
> 
> Und genau diese andere Syntax wüßte ich gerne.

Zu Pointer und Funktionen:

http://www.newty.de/fpt/index.html

Für's Grundlegende zum Auffrischen:

http://www.bg.bib.de/FHDW/Intranet/prg/docs/CPPkompakt.pdf

Mein PDF hatte zwar eine total verfusselte Seitennummerierung, war aber
gut lesbar und verständlich.

Marc

[toc] | [prev] | [next] | [standalone]


#204058

FromHans-Peter Diettrich <DrDiettrich1@aol.com>
Date2016-03-11 13:24 +0100
Message-ID<dkfrogFgl9sU1@mid.individual.net>
In reply to#203944
Marc Santhoff schrieb:
> Hans-Peter Diettrich <DrDiettrich1@aol.com> schrieb:
> 
>> Marc Santhoff schrieb:
>>
>>> Der ganze Kram funktioniert größtenteils exakt so, wie in Object
>>> Pascal. VMT, abstrakte und virtuelle Methoden, Klassendeklarationen,
>>> etc. Nur, daß eben eine andere Syntax benutzt wird.
>> Und genau diese andere Syntax wüßte ich gerne.
> 
> Zu Pointer und Funktionen:
> 
> http://www.newty.de/fpt/index.html

Danke :-)

Es wurden da zwar nicht alle meine Fragen beantwortet, aber hilfreich 
war es doch. Nach einigen Versuchen kann ich nur unterstreichen, daß man 
tunlichst ein typedef verwenden sollte!

Die neue Bibliothek erzeugt grade mal 20 Bytes mehr Code, wovon 8 Byte 
auf eine Dummy-Funktion (zur Vermeidung von NULL Pointern) entfallen :-)
Jetzt muß ich noch die Kompatibilität testen, und die mitgelieferten 
Beispiele anpassen.


> Für's Grundlegende zum Auffrischen:
> 
> http://www.bg.bib.de/FHDW/Intranet/prg/docs/CPPkompakt.pdf
> 
> Mein PDF hatte zwar eine total verfusselte Seitennummerierung, war aber
> gut lesbar und verständlich.

Die Seitennummern sind tatsächlich sehr seltsam. Ansonsten sieht es gut aus.

DoDi

[toc] | [prev] | [next] | [standalone]


#203959

FromEdzard Egberts <ed_09@tantec.de>
Date2016-03-10 08:51 +0100
Message-ID<nbr91m$rv5$1@news.albasani.net>
In reply to#203890
Hans-Peter Diettrich wrote:
> 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
> mit einem Methoden-Pointer erledigen läßt :-(
> (Singleton)

Ein Singleton kann eigentlich komplett statisch sein, so dass Du die
einfacheren C-Funktionspointer verwenden kannst, indem Du die Methoden
static definierst und ggf. einen this-Pointer auf Deine Instanz übergibst:

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);


Die Dekoder-Funktionen müssen dann noch nicht einmal Methoden sein,
sondern können extern definiert werden. Die Klasse könnte man so auf ein
Datenobjekt beschränken, das die Parameter für die Dekoder enthält.


Eine echte C++-Lösung wäre dagegen die Verwendung eines Interface, mit
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; }
};

Verwendung mit Aufruf über die Basisklasse:

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
if (pFoo->decode()) do_anything();	// ausführen

[toc] | [prev] | [next] | [standalone]


#203983

FromHans-Peter Diettrich <DrDiettrich1@aol.com>
Date2016-03-10 16:33 +0100
Message-ID<dkdk1sFemhsU1@mid.individual.net>
In reply to#203959
Edzard Egberts schrieb:
> Hans-Peter Diettrich wrote:
>> 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
>> mit einem Methoden-Pointer erledigen läßt :-(
>> (Singleton)
> 
> Ein Singleton kann eigentlich komplett statisch sein, so dass Du die
> einfacheren C-Funktionspointer verwenden kannst, indem Du die Methoden
> static definierst und ggf. einen this-Pointer auf Deine Instanz übergibst:

In diesem Fall würde ich die Instanz ganz wegoptimieren. Bislang werden 
die zugehörigen Daten in 3 Strukturen gespeichert, eine statische für 
den Interrupt-Handler, eine für das dekodierte Ergebnis (Parameter), und 
dann noch die Klasse selbst. Das Ergebnis habe ich momentan bereits in 
die Klasse integriert, es könnte aber auch komplett global werden und 
auch die Elemente der Klasse enthalten.
[...]
> int main()
> {
> 	IRrecv irrecv;
> 	irrecv.read(IRrecv::decodeNEC);

Hier stört mich noch der aufwendige Parameter (Tippfehler!), dafür 
sollte ich wohl noch Makros definieren.

> Die Dekoder-Funktionen müssen dann noch nicht einmal Methoden sein,
> sondern können extern definiert werden. Die Klasse könnte man so auf ein
> Datenobjekt beschränken, das die Parameter für die Dekoder enthält.

Das war auch meine erste Idee. Doch dann habe ich mich für die 
Beibehaltung der Klasse entschieden, mit den Standard-Methoden begin(), 
available() und read(), die jeder Arduino Programmierer von den anderen 
Stream-Klassen gewohnt ist.

> Eine echte C++-Lösung wäre dagegen die Verwendung eines Interface, mit
> dem sich die Funktionen als Objekt handhaben lassen:

Dagegen spricht die universelle decode() Methode, die alle verfügbaren 
Dekoder durchprobiert, und die weiterhin nutzbar sein sollte. Die müßte 
dann auf Instanzen aller abgeleiteten Klassen zugreifen, mit höherem 
Speicherbedarf (zumindest bei den VMT).

Vielen Dank für die ausführlichen Codechnipsel :-)

Zumindest weiß ich jetzt, was für eine Sorte Pointer ich brauche, und 
hoffe, daß ich nun auch die Lücken im ursprünglichen Beitrag richtig 
füllen kann.

DoDi

[toc] | [prev] | [next] | [standalone]


Page 1 of 2  [1] 2  Next page →

Back to top | Article view | de.sci.electronics


csiph-web