Klasse in Arduino-C++

OP (Firma: Q3) #6689500
Lesenswert?

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.
#6689523
Lesenswert?

Irgend W. schrieb:
> "Ardino-C++" gibt es nicht, dass ist ganz stink "normales" C++ mit GCC
> als toolchain im Hintergrund.
> Du kannst also jeder x-beliebige Beschreibung zu dem Thema nutzen die du
> im I-Net zu tausenden findest.
> Z.B.:
> https://en.cppreference.com/w/cpp/language/class
> http://www.cplusplus.com/doc/tutorial/classes/

Bedenke jedoch, dass die Std lib nicht zur Verfügung steht.
OP (Firma: Q3) #6689894
Lesenswert?

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
2
      buttonPin(buttonPin),
3
      outputPin(outputPin)
4
    {}
OP (Firma: Q3) #6689980
Lesenswert?

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 :-)
Gast #6689992
Lesenswert?

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++?
Gast #6690012
Lesenswert?

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
#6690017
Lesenswert?

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.
OP (Firma: Q3) #6690025
Lesenswert?

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.
Gast #6690040
Lesenswert?

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
Gast #6690064
Lesenswert?

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?
#6690137
Lesenswert?

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.
#6690158
Lesenswert?

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.
#6690318
Lesenswert?

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.
#6690937
Lesenswert?

Wilhelm M. schrieb:
> A(int a) : m{a}{} // Element-Initialisierungslist mit
> Elementinitialisierer

Aber wir sprachen doch von einer Initialisierung ohne 
Initialisierungsliste.
Also so:
1
struct A
2
{
3
    A(int) {}
4
};
5

6
struct B
7
{
8
   B(int x)
9
   {
10
        /* Initialisierung von a mit übergebenem Wert
11
           aber ohne Initialisierungsliste */
12
   } 
13

14
   A a;
15
}
Und ich wüsste nicht, wie das gehen soll.
#6690950
Lesenswert?

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.
Persönliche Seite #6690962
Lesenswert?

Wilhelm M. schrieb:
> Dann mache dazu mal ein Beispiel.
1
class X {
2
  public:
3
    X () {}
4
    int& ref;
5
};

Resultiert in Compiler-Fehler. Man braucht
1
class X {
2
  public:
3
    X () {}
4
    int y;
5
    int& ref { y };
6
};

oder
1
class X {
2
  public:
3
    X () : ref {y} {}
4
    int y;
5
    int& ref;
6
};

Einen dritten Weg gibt es nicht. Insbesondere geht auch so etwas wie
1
class X {
2
  public:
3
    X () { ref = y; }
4
    int y;
5
    int& ref;
6
};

nicht, und macht auch überhaupt keinen Sinn (Referenzen selbst sind 
nicht zuweisbar).
#6690990
Lesenswert?

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.
#6691007
Lesenswert?

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.
Gast #6691009
Lesenswert?

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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren