Kann mir bitte jemand einen Link zu einem verständlichen (mögl.
deutschen) Tutorial geben, in dem beschrieben wird, wie man im
Ardino-C++ (in der Arduino-IDE) eine funktionierende Klasse inkl.
Construktor mit Parametern erstellt?
Ich habe Erfahrungen (und bisher kein Problem) im Estellen von Klassen
in Java, Processing und Xojo.
Was ich bei meinem ersten Versuch aber diesbezüglich in der Arduino-IDE
erlebt habe, hat mich echt zweifeln lassen. Ich bekam die (m.E.)
absurdesten Fehlermekdungen angezeigt. Wer hat sich das bloß ausgedacht
... ?
Ach ja: Danke für Tips.
Frank E. schrieb:> Ich bekam die (m.E.) absurdesten Fehlermekdungen angezeigt.
Du kannst auch mal hier posten, was du versucht hast, und welche
"absurde" Meldung du dann bekommen hast. Dann kann dir bestimmt jemand
erklären, was falsch ist und warum der Compiler nun gerade so darauf
reagiert hat.
noiasca schrieb:> hier habe ich ein Beispiel mit einer Klasse für ein Relais, wo der> Pin> mittels Initialisierungsliste im Konstruktor übergeben wird:>> https://werner.rothschopf.net/202003_arduino_retriggerbares_nachlaufrelais_oop.htm
DAS sieht sehr gut aus!
Einen Constructor SO zu schreiben, darauf wäre ich (aufgrund meiner
bescheidenen Java-Erfahrungen) nie im Leben gekommen. Ich habe auch
nirgendwo so ein schönes Beispiel gesehen. Die meisten Dokus machen
sowas durch Darstellung aller möglichen Optionen völlig unverständlich.
Eine Doku ist eben kein Lehrbuch. Na gut ...
Bei den sonstigen Methoden wie Setter/Getter ist das ja nicht so
drastisch ... sicher hätte ich es mir irgendwann angelesen ... Danke.
1
retriggerOffDelay(byte buttonPin, byte outputPin) : // the constructor
Frank E. schrieb:> Einen Constructor SO zu schreiben, darauf wäre ich (aufgrund meiner> bescheidenen Java-Erfahrungen) nie im Leben gekommen.
Wer gedacht, dass java != C++ ist? Wie hättest du es denn in java
gemacht?
mh schrieb:> Frank E. schrieb:>> Einen Constructor SO zu schreiben, darauf wäre ich (aufgrund meiner>> bescheidenen Java-Erfahrungen) nie im Leben gekommen.>> Wer gedacht, dass java != C++ ist? Wie hättest du es denn in java> gemacht?
Na als "scheinbar" ganz normale Methode aber ohne Rückgabe, auch kein
Void, mit dem gleichen Namen wie die Klasse. Bei Bedarf in Varianten mit
unterschiedlicher Anzahl von Parametern ...
Dass man in C++ beim Instanziieren nicht "new" verwendet, darauf war ich
schon alleine gekommen :-)
mh schrieb:> Frank E. schrieb:>> Einen Constructor SO zu schreiben, darauf wäre ich (aufgrund meiner>> bescheidenen Java-Erfahrungen) nie im Leben gekommen.>> Wer gedacht, dass java != C++ ist? Wie hättest du es denn in java> gemacht?Frank E. schrieb:> Na als "scheinbar" ganz normale Methode aber ohne Rückgabe, auch kein> Void, mit dem gleichen Namen wie die Klasse. Bei Bedarf in Varianten mit> unterschiedlicher Anzahl von Parametern ...
Wo genau ist da jetzt der unterschied zu C++?
Frank E. schrieb:> Dass man in C++ beim Instanziieren nicht "new" verwendet, darauf war ich> schon alleine gekommen :-)
Du darfst new verwenden wenn du das Objekt auf dem Heap haben willst,
ansonste wird das Objekt auf dem Stack angelegt
Frank E. schrieb:> Na als "scheinbar" ganz normale Methode aber ohne Rückgabe, auch kein> Void, mit dem gleichen Namen wie die Klasse. Bei Bedarf in Varianten mit> unterschiedlicher Anzahl von Parametern ...
Ist in Java exakt gleich, ohne Rückgabe und n Varianten mit
unterschiedlichen Parametern
mh schrieb:> mh schrieb:>> Frank E. schrieb:>>> Einen Constructor SO zu schreiben, darauf wäre ich (aufgrund meiner>>> bescheidenen Java-Erfahrungen) nie im Leben gekommen.>>>> Wer gedacht, dass java != C++ ist? Wie hättest du es denn in java>> gemacht?>> Frank E. schrieb:>> Na als "scheinbar" ganz normale Methode aber ohne Rückgabe, auch kein>> Void, mit dem gleichen Namen wie die Klasse. Bei Bedarf in Varianten mit>> unterschiedlicher Anzahl von Parametern ...> Wo genau ist da jetzt der unterschied zu C++?
Einen Unterschied gibt es in C++ noch: Man verwendet
Initialisierungslisten.
mh schrieb:> Frank E. schrieb:>> Na als "scheinbar" ganz normale Methode aber ohne Rückgabe, auch kein>> Void, mit dem gleichen Namen wie die Klasse. Bei Bedarf in Varianten mit>> unterschiedlicher Anzahl von Parametern ...> Wo genau ist da jetzt der unterschied zu C++?
Na dann guck dir doch mal mein Code-Zitat von 12:17 an:
- Doppelpunkt nach dem Funktionskopf
- zwei (scheinbare) Methodenaufrufe mit dem gleichen Namen wie die
Parameter
- ein leeres Paar geschweifte Klammern ...
Kann man mit Sicherheit alles logisch erklären, für mich war es aber
erstaunlich fremd, fremder jedenfalls als Java. Ist aber auch egal, ich
habs zwar noch nicht völlig verstanden, kann es aber anwenden. Der Rest
kommt sicher im Laufe der Zeit.
mh schrieb:> Man kann sie verwenden, niemand zwingt einen dazu.
Ist aber besser, weil man dann auch constexpr nutzen kann und die
Variablen nie einen uninitialisierten Zustand haben.
Wie man Klassen in C++ implementiert steht in jedem C++-Buch. In ein
solches zu schauen ist hier sowieso eine gute Idee, da Arduino-Tutorials
vieles verkürzt, vereinfacht oder gar falsch darstellen. C++ ist komplex
und hat viele Fallstricke, weshalb man das am Besten konsequent mit
einem Buch lernt, z.B.:
https://stackoverflow.com/a/388282
Programmierer schrieb:> mh schrieb:>> Man kann sie verwenden, niemand zwingt einen dazu.>> Ist aber besser, weil man dann auch constexpr nutzen kann und die> Variablen nie einen uninitialisierten Zustand haben.
Klar ist das besser, auch wenn deine Begründung unvollständig und nicht
unbeding richtig ist. Aber wenn der TO seinen Constructor auf Java-Art
schreiben möchte kann er das machen. Es zwingt ihn niemand,
Initialisierungslisten zu verwenden.
Frank E. schrieb:> mh schrieb:>>> Frank E. schrieb:>>> Na als "scheinbar" ganz normale Methode aber ohne Rückgabe, auch kein>>> Void, mit dem gleichen Namen wie die Klasse. Bei Bedarf in Varianten mit>>> unterschiedlicher Anzahl von Parametern ...>> Wo genau ist da jetzt der unterschied zu C++?>> Na dann guck dir doch mal mein Code-Zitat von 12:17 an:> [...]
Und warum hast du ihn nicht auf Java-Art geschrieben? Was war da dein
Problem?
Frank E. schrieb:> Bei den sonstigen Methoden wie Setter/Getter ist das ja nicht so> drastisch ... sicher hätte ich es mir irgendwann angelesen ... Danke.> retriggerOffDelay(byte buttonPin, byte outputPin) : // the constructor> buttonPin(buttonPin),> outputPin(outputPin)> {}
Und glaube keinen beliebigen Internetquellen, denn das verlinkte ist in
der Tat falsch - man achte auf die Schreibweise ;-)
Und wer neben einem vermeintlichen CTor dann noch so einen Kommentar
schreibt, dem sollte man besser aus dem Weg gehen.
Nimm ein C++ Buch wie den Breymann und mache es Dir auf der Couch
gemütlich.
mh schrieb:> Rolf M. schrieb:>> Einen Unterschied gibt es in C++ noch: Man verwendet>> Initialisierungslisten.> Man kann sie verwenden, niemand zwingt einen dazu.
Das kommt auf den Anwendungsfall an. Man sollte sie in der Regel
verwenden, manchmal muss man sie auch zwingend verwenden, z.B. wenn man
ein Objekt einer Klasse erstellen will, die keinen Default-Konstruktor
hat. Es muss einem eben auch klar sein, dass Initialisierung und
Zuweisung zwei unterschiedliche Dinge sind, die sich unterschiedlich
auswirken können.
Aber ja, oft geht auch der Umweg über eine Default-Initialisierung mit
nachfolgender Zuweisung statt einer direkten Initialisierung.
Rolf M. schrieb:> Das kommt auf den Anwendungsfall an. Man sollte sie in der Regel> verwenden, manchmal muss man sie auch zwingend verwenden, z.B. wenn man> ein Objekt einer Klasse erstellen will, die keinen Default-Konstruktor> hat.
Ein Objekt eines Typs ohne Std-CTor kann ich auch über einen
Elementinitialisierer initialisieren.
Rolf M. schrieb:> Aber ja, oft geht auch der Umweg über eine Default-Initialisierung mit> nachfolgender Zuweisung statt einer direkten Initialisierung.
Und genauso oft nicht!
Es soll DT geben, die nicht kopierzuweisbar sind ;-)
Wilhelm M. schrieb:> Ein Objekt eines Typs ohne Std-CTor kann ich auch über einen> Elementinitialisierer initialisieren.
Ja, kann man heute auch machen, sofern keiner der Konstruktor-Parameter
wiederum von Konstruktor-Parametern des äußeren Objekts abhängt. Ich
hatte das nicht erwähnt, weil ich's nicht unnötig kompliziert machen
wollte.
Spielt ja an sich auch keine Rolle für die Frage, warum man
Initialisierungslisten gegenüber Zuweisungen und ähnlichem innerhalb des
Konstruktors vorziehen sollte.
Wilhelm M. schrieb:> Rolf M. schrieb:>> Aber ja, oft geht auch der Umweg über eine Default-Initialisierung mit>> nachfolgender Zuweisung statt einer direkten Initialisierung.>> Und genauso oft nicht!> Es soll DT geben, die nicht kopierzuweisbar sind ;-)
Hab doch geschrieben, dass es je nach Fall gehen kann oder auch nicht.
Wilhelm M. schrieb:> Rolf M. schrieb:>> Ja, kann man heute auch machen,>> Nein, das ging schon immer.> Was Du meinst sind die in-class-initializer in brace-or-equal-form.
Dann weiß ich nicht, was du meinst. Ich kenne außer per initializer list
und in-class keine Möglichkeit, eine Membervariable explizit zu
initialisieren.
Wilhelm M. schrieb:> A(int a) : m{a}{} // Element-Initialisierungslist mit> Elementinitialisierer
Aber wir sprachen doch von einer Initialisierung ohne
Initialisierungsliste.
Also so:
Rolf M. schrieb:> Aber wir sprachen doch von einer Initialisierung ohne> Initialisierungsliste.
Ja, das habe ich Dir gezeigt.
Das mit dem ctor-Parameter hast Du jetzt hinzugefügt.
Ich habe nur oben gesagt, dass es eben DT geben kann, die vllt. nicht
kopier/verschiebungszuweisbar sind.
Mag alles ein großes Missverständnis zu sein...
Wilhelm M. schrieb:> Rolf M. schrieb:>> Aber wir sprachen doch von einer Initialisierung ohne>> Initialisierungsliste.>> Ja, das habe ich Dir gezeigt.
Es tut mir leid, aber ich weiß echt nicht, worauf du hinaus willst.
> Das mit dem ctor-Parameter hast Du jetzt hinzugefügt.
Das hatte ich nur gemacht, damit ich die in-Class-Initialisierung als
zweite Option nicht nochmal explizit erwähnen muss.
Du hast dafür übrigens int statt einer Klasse ohne Default-Konstruktor
verwendet.
> Ich habe nur oben gesagt, dass es eben DT geben kann, die vllt. nicht> kopier/verschiebungszuweisbar sind.
Und ich schrieb, dass man für eine Klasse ohne Default-Konstruktor die
Initialisierungsliste braucht. Darauf meintest du, dass es auch über
einen "Elementinitialisierer" ginge. Ich war davon ausgegangen, das du
damit in-Class-Initialisierung meinst, was du verneint hast. Also bin
ich davon ausgegangen, dass du eine dritte, mir unbekannte Art meinst,
die weder in-Class, noch per Initialisierungsliste passiert. Dein
Beispiel zeigt aber jetzt nur einmal per Initialisierungsliste und
zweimal in-Class.
> Mag alles ein großes Missverständnis zu sein...
Vermutlich.
Rolf M. schrieb:> Und ich schrieb, dass man für eine Klasse ohne Default-Konstruktor die> Initialisierungsliste braucht.
Dann mache dazu mal ein Beispiel.
Niklas G. schrieb:> Wilhelm M. schrieb:>> Dann mache dazu mal ein Beispiel.> class X {> public:> X () {}> int& ref;> };
Das ist klar.
Er schrieb: ein DT ohne Std-ctor(!) kann nur über die Elementinit-liste
initialisiert werden. Als es geht um die Eigenschaft: Std-ctor ja oder
nein.
Nicht das was Du geschrieben hast.
Wilhelm M. schrieb:> Rolf M. schrieb:>> Und ich schrieb, dass man für eine Klasse ohne Default-Konstruktor die>> Initialisierungsliste braucht.>> Dann mache dazu mal ein Beispiel.
??
Das hab ich doch gerade in
Beitrag "Re: Klasse in Arduino-C++" getan.
Wilhelm M. schrieb:> Als es geht um die Eigenschaft: Std-ctor ja oder> nein.
"int&" hat keinen Standard-CTor. Somit bleiben eben diese beiden
Möglichkeiten - Initialisierungsliste im Konstruktor oder
In-Class-Initialization. Eine Initialisierungsliste ohne Konstruktor
gibt es in C++ nicht (in anderen Sprachen wie Scala oder Kotlin schon).
Niklas G. schrieb:> Das ist die in-Class-Initialisierung und keine Initializer-Liste. Also> eine der beiden genannten Möglichkeiten.
Das sage ich doch die ganze Zeit.
Nur Rolf behauptet, das eine in-class init für einen DT ohne std-ctor
nicht geht. Der DT int hat auch einen std-ctor. Es ging nicht um
Referenzen, das hast Du erst ins Spiel gebracht.
Wilhelm M. schrieb:> Niklas G. schrieb:>> Das ist die in-Class-Initialisierung und keine Initializer-Liste. Also>> eine der beiden genannten Möglichkeiten.>> Das sage ich doch die ganze Zeit.> Nur Rolf behauptet, das eine in-class init für einen DT ohne std-ctor> nicht geht.
Hä? Das hab ich nie behauptet. Das Gegenteil davon habe ich hier
geschrieben:
Rolf M. schrieb:> Wilhelm M. schrieb:>> Ein Objekt eines Typs ohne Std-CTor kann ich auch über einen>> Elementinitialisierer initialisieren.>> Ja, kann man heute auch machen, sofern keiner der Konstruktor-Parameter> wiederum von Konstruktor-Parametern des äußeren Objekts abhängt.
Darauf hast du geantwortet:
Wilhelm M. schrieb:> Nein, das ging schon immer.> Was Du meinst sind die in-class-initializer in brace-or-equal-form.
… und genau die meinte ich auch. Du hast die aber anscheinend nicht
gemeint, deswegen wollte ich wissen, was du denn dann meintest.
Wilhelm M. schrieb:> Geht doch.
Das ist immer noch keine Klasse ohne Default-Konstruktor, sondern int.
Damit ging das tatsächlich schon immer. Instanzen von Klassen kann man
aber erst seit C++11 in-class initialisieren.
Rolf M. schrieb:> Und ich schrieb, dass man für eine Klasse ohne Default-Konstruktor die> Initialisierungsliste braucht
Das hast Du geschrieben.
Aber das ist ja nicht zwingend: wie ich Dir gezeigt habe, kann man einen
DT ohne std-ctor auch in-class mit einem allg. ctor initialisieren.
Wilhelm M. schrieb:> Rolf M. schrieb:>> Und ich schrieb, dass man für eine Klasse ohne Default-Konstruktor die>> Initialisierungsliste braucht>> Das hast Du geschrieben.
Ja, das habe ich geschrieben. Darauf hast du die
in-class-Initialisierung erwähnt, was ich dann bestätigt habe. Siehe
obiges zitiertes Posting von mir. Hier nochmal:
Rolf M. schrieb:> Ja, kann man heute auch machen, sofern keiner der Konstruktor-Parameter> wiederum von Konstruktor-Parametern des äußeren Objekts abhängt.
Du hast dann geschrieben, das ginge schon immer, aber das geht erst seit
C++11.
> Aber das ist ja nicht zwingend: wie ich Dir gezeigt habe, kann man einen> DT ohne std-ctor auch in-class mit einem allg. ctor initialisieren.
Das habe ich nie bestritten.
Wilhelm M. schrieb:> Rolf M. schrieb:>> Und ich schrieb, dass man für eine Klasse ohne Default-Konstruktor die>> Initialisierungsliste braucht>> Das hast Du geschrieben.> Aber das ist ja nicht zwingend: wie ich Dir gezeigt habe, kann man einen> DT ohne std-ctor auch in-class mit einem allg. ctor initialisieren.
Mensch so schwer ist das doch nicht. es Geht Rolf die ganze Zeit um eine
Klasse mit Member ohne default-ctor und nicht um eine Klasse ohne
default-ctor.