Forum: PC-Programmierung Klasse mit einzelnen :


von C-Noob (Gast)


Lesenswert?

Hallo,

ich bin über eine Schreibweise gestoplert, die ich so noch nie gesehen 
habe.
1
Lixie::Lixie(const uint8_t pin, uint8_t nDigits):NumDigits(nDigits), NumLEDs(nDigits * LEDsPerDigit){
2
  leds = new CRGB[NumLEDs];
3
  led_states = new byte[NumDigits * 3]; // 24 bits for 20 LED states
4
  colors = new CRGB[NumDigits];
5
  colors_off = new CRGB[NumDigits];
6
  digit_brightness = new byte[NumDigits];
7
  
8
  build_controller(pin);
9
}

Ist eine Funktion einer Klasse, okay. Aber was macht der : nach den 
Parametern der Funktion. Scheint ja irgenwie nochmal Variablen zu 
definieren, nur diese Art das zu machen habe ich noch nie gesehen. Weiß 
jemand wie man das nennt, so dass ich das mal Googlen kann?

von Yalu X. (yalu) (Moderator)


Lesenswert?


: Bearbeitet durch Moderator
von Eric B. (beric)


Lesenswert?

C-Noob schrieb:
> Hallo,
>
> ich bin über eine Schreibweise gestoplert, die ich so noch nie gesehen
> habe.
> Lixie::Lixie(const uint8_t pin, uint8_t nDigits):NumDigits(nDigits),
> NumLEDs(nDigits * LEDsPerDigit){
...
> Ist eine Funktion einer Klasse, okay.

Nein, das ist ein Constructor.
Die Liste nach dem : ist die sogenannte "initializer list".

EDIT: Yalu war schneller :-)

: Bearbeitet durch User
von C-Noob (Gast)


Lesenswert?

Super, danke. Jetzt hat das Kind einen Namen.

von MaWin (Gast)


Lesenswert?

Die Frage wäre, wozu man das braucht.

Stell dir eine Klasse vor, deren Contructor zwingend einen Parameter 
benötigt, es gibt keinen Constructor ohne Parameter.
1
class x
2
{
3
public:
4
  x(int a);
5
}
Ein Element dieser Klasse soll nun Membervariable einer anderen Klasse 
werden
1
class y
2
{
3
  x my_x;
4
public:
5
  y();
6
}
Man kann nun im Contructor von y nicht einfach x erzeugen
1
y::y()
2
{
3
  // initialisierung
4
  my_x=x(4);
5
}
weil es dann eine Phase gibt zwischen dem Anfang von y::y und dem Teil 
wo hier der Kommentar // Initialisierung streh bis zum my_x = x(4); wo 
es das my_x zwar syntaxmässig gibt, es aber nicht erzeugt werden konnte, 
weil es für ihn keinen Constructor ohne Parameter gibt und C++ ja nicht 
wissen kann welchen Parameter es hätte einsetzen sollen.

Weil das nicht geht, gibt es einen Compilerfehler. Der einzige Weg 
drumrum ist die Initializer List die vor dem eigentlichen Code des 
Constructors ausgeführt wird
1
y::y():my_x(4)
2
{
3
  // initialisiert
4
}
Dieser hack, um syntaktisch doch das zu ermöglichen, was eigentlich 
nicht geht, hat den Nachteil das der Initializer vor dem eigentlichen 
Contructor code steht und keine Berechnungen durchgeführt werden können, 
um zum Parameter zu kommen.

Da braucht es dann eine Funktion:
1
int calcparm(void)
2
{
3
   time_t t;
4
   time(&t);
5
   struct tm * now=localtime(t);
6
   return now.tm_min+now.tm_sec;
7
}
8
y::y:my_x(calcparam())
9
{
10
  // bingo
11
}
Diese kranke Syntax erlaubt es nicht, 2 member-variablen auf derselben 
Teilberechnung aufzusetzen, weil die calcparm Funktionen keine 
gemeinsamen Variablen nutzen können.
1
int calcsec(void)
2
{
3
  time t;
4
  time(&t);
5
  struct tm *now=localtime(t);
6
  return now.tm_sec;
7
}
8
int calcmin(void)
9
{
10
  time t;
11
  time(&t);
12
  struct tm *now=localtime(t);
13
  return now.tm_min;
14
class 
15
{
16
  x my_sec;
17
  x my_min;
18
public:
19
  y():my_sec(calcsec()),my_min(calcmin())
20
  {
21
  }
22
}
Es geht nicht, min und sec aus derselben Zeit t abzuleiten, sondern man 
muss sie 2 Mal holen. C++ ist ein unreifer hack.

von BobbyX (Gast)


Lesenswert?

MaWin schrieb:
> Ein Element dieser Klasse soll nun Membervariable einer anderen Klasse
> werden

Wer so etwas schreibt hat nix von C++ oder OOP verstanden....

von C-Noob (Gast)


Lesenswert?

Hallo MaWin,

danke für die ausführliche Beschreibung, in welchen Fällen diese 
Initialisierung zum Tragen kommen kann. In dem Code gibt es zwar keine 
weiteren Klassen. Zumindest werden die Werte NumDigits und NumLEDs noch 
in anderen Funktionen der gleichen Klasse verwendet.

von Wilhelm M. (wimalopaan)


Lesenswert?

MaWin schrieb:
> Weil das nicht geht, gibt es einen Compilerfehler.

Blödsinn.

MaWin schrieb:
> hat den Nachteil das der Initializer vor dem eigentlichen
> Contructor code steht und keine Berechnungen durchgeführt werden können,
> um zum Parameter zu kommen.

Nochmal Blödsinn.

von Wilhelm M. (wimalopaan)


Lesenswert?

MaWin schrieb:
> C++ ist ein unreifer hack.

Nur für jemanden, der so absolut keine Ahnung hat, wie Du.

von Wilhelm M. (wimalopaan)


Lesenswert?

Eric B. schrieb:
>> Ist eine Funktion einer Klasse, okay.
>
> Nein, das ist ein Constructor.

Doch, ein ctor ist auch eine Elementfunktion, nur eben eine besondere.

Deswegen heißen bspw. std-ctor, cctor, mctor, cassign-op, massign-op und 
dtor auch special-member-functions.

von Dirk K. (merciless)


Lesenswert?

Die initializer list kann auch verwendet werden,
um andere Konstruktoren aufzurufen. Diese können
aus der eigenene Klasse sein oder geerbt.

merciless

von Wilhelm M. (wimalopaan)


Lesenswert?

Dirk K. schrieb:
> Die initializer list kann auch verwendet werden,
> um andere Konstruktoren aufzurufen. Diese können
> aus der eigenene Klasse sein oder geerbt.

Ja, genau:

Kleiner Fallstrick: die delegate-ctor müssen das erste Element der 
init-list sein.

von Dirk K. (merciless)


Lesenswert?

Wilhelm M. schrieb:
> Kleiner Fallstrick: die delegate-ctor müssen das erste Element der
> init-list sein.
Ich hoffe der TO liest eine gute Dokumentation
der initializer list, es gibt ja noch mehr
Fallstricke ;)

Meine Empfehlung: Sparsam verwenden.

merciless

von Wilhelm M. (wimalopaan)


Lesenswert?

Dirk K. schrieb:
> Ich hoffe der TO liest eine gute Dokumentation
> der initializer list

Du meinst "member initializer list", sonst schaut er bei 
<initializer_list> ;-)

von Oliver S. (oliverso)


Lesenswert?

MaWin schrieb:
> Stell dir eine Klasse vor, deren Contructor zwingend einen Parameter
> benötigt, es gibt keinen Constructor ohne Parameter.

Wenn das so ist, es auch einen (guten) Grund dafür geben. In dem Fall 
sollte man in der grundlegende Struktur seiner Daten darauf Rücksicht 
nehmen.

MaWin schrieb:
> Man kann nun im Contructor von y nicht einfach x erzeugeny::y()
> {
>   // initialisierung
>   my_x=x(4);
> }

C++ (wie C) unterscheidet halt im Zusammenhang mit Variablen (u.a) 
Deklaration, Definition, und Zuweisung.
Abgesehen davon gibt es seit ca. 2011 sowas wie C++11.

Oliver

von mh (Gast)


Lesenswert?

Dirk K. schrieb:
> Meine Empfehlung: Sparsam verwenden.

Wenn du std::initilizer_list meinst kann ich dir zustimmen. member 
initilizer lists, sollte man dagegen immer nutzen, wenn möglich. Damit 
hat man schon die halbe Strecke zur exception safety geschafft. 
Zusätzlich ist es schneller und sparsamer und meiner Meinung nach 
deutlich besser lesbar, wenn korrekt formatiert.

von Wilhelm M. (wimalopaan)


Lesenswert?

mh schrieb:
> Wenn du std::initilizer_list meinst kann ich dir zustimmen. member
> initilizer lists, sollte man dagegen immer nutzen, wenn möglich. Damit
> hat man schon die halbe Strecke zur exception safety geschafft.

Sehr richtig.
Und damit sich nachträglich keine Fehler einschleichen: 
in-class-initializer.

von Oliver S. (oliverso)


Lesenswert?

Wilhelm M. schrieb:
> Sehr richtig.
> Und damit sich nachträglich keine Fehler einschleichen:
> in-class-initializer.

Auf jeden Fall. Was dann aber eben keine member initializer lists mehr 
sind.

Oliver

von mh (Gast)


Lesenswert?

Wilhelm M. schrieb:
> in-class-initializer

Das hat allerdings wieder den Nachteil, dass man an mindestens zwei 
Stellen gucken muss wie Member initialisiert wurden.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.