Zwei Fragen zu möglichen Schreibarten in C++
-
Hallo,
ich lese zur Zeit "C++ für Dummies" und bin bald fertig damit. Aber schon eine ganze Weile quälen mich zwei Fragen, die mir das Verständnis der Quelltexte im Buch erschweren.Die erste Frage:
Wenn ich einen Zeiger oder eine Referenz deklariere oder als Argument in einer Funktioen erwarte, sind dann folgende Varianten bedeutungsgleich?
Variante 1
Testklasse *pListe[10]; //und Funktion(Testklasse *pListe[10]) {} //bzw. Testklasse &Objekt; //und Funktion(Testklasse &Objekt) {}Variante 2
Testklasse* pListe[10]; //und Funktion(Testklasse* pListe[10]) {} //bzw. Testklasse& Objekt; //und Funktion(Testklasse& Objekt) {}Eigentlich sind Leerzeichen usw. ja in C++-Quelltext egal, aber bei Zeigern hat ja auch:
char* pZeigerAufEtwas; //und *pZeigerAufEtwas = "a";Verschiedene Bedeutungen, nur weil das Sternchen direkt vor dem Variablennamen steht oder nach dem Typ.
Die Zweite Frage wäre z.B. bei folgender Klasse:
class Testklasse : public ZweiteKlasse { public: Testklasse (int Name, int Typ, char* Text, ZweiteKlasse& EinObjekt) : DerName(Name), DerTyp(Typ), Testobjekt(EinObjekt) { //das char* Text verarbeiten } protected: int DerName; int DerTyp; ZweiteKlasse Testobjekt; }Hinter dem ":" in Zeile 5, was darf da alles genau stehen? Soweit ich das jetzt verstanden habe, darf mit man dort Variablen mit der Schreibweise Variable(Wert) Werte zuordnen und beliebige Funktionen aufrufen. Wenn man dort aber alles darf, wieso macht man es dann nicht in den geschweiften Klammern?
Ich hoffe jemand kann mir das erklären und meine Verwirrung ein wenig senken. Schonmal vielen Dank im Voraus, allein schon für's lesen.

-
Frage 1: Ist genau das gleiche. Was sinnvoller ist, ist wohl eine philosophische Frage.
Frage 2: Das hinter dem : nennt sich Initialisierungsliste und dient zum erstmaligen initialisieren von Member Variablen einer Klasse. Du darfst hier ausschließlich Variablen einer Klasse mit ihrem Konstruktor initialisieren.
Funktionen dürfen nicht aufgerufen werden.
Der Vorteil ist, du kannst hier auch const Variablen initialisieren:class Foo { private: const int bar; // kann hier nicht initialisiert werden public: Foo() : bar(5) // initialisiert bar mit 5 { // Rest vom Code } };
-
Zur ersten Frage:
Die beiden Varianten sind bedeutungsgleich. Allerdings bevorzuge ich die Variante mit dem Asterisk (*) direkt vor dem Variablennamen, denn sonst könnte man leicht folgende (falsche) Schlussfolgerung ziehen:char* str1, str2; // str1 vom Typ char*, str2 vom Typ char; man denkt, beide seien vom Typ char* char *str1, *str2; // beide vom Typ char*Zur zweiten Frage:
Hinter dem : kannst du durch Komma getrennt einerseits Membervariablen mit einem Wert (auch Rückgabewerte von Funktionen sind möglich) oder auch die Konstruktoren der Basis-Klassen (in deinem Beispiel könntest du auch noch... Testklasse () : ZweiteKlasse (parameter, fuer, Konstruktor, von, ZweiteKlasse) {}schreiben).
-
Beide Varianten bewirken dasselbe.
char* pZeigerAufEtwas; //und *pZeigerAufEtwas = "a";Der Vergleich zieht nicht ganz, da * hier zwar zwei unterschiedliche Bedeutungen hat, aber Leerzeichen hier ebenfalls keine Rolle spielen.
Muss übrigens 'a' lauten (einzelnes Zeichen).Die Liste nach dem Doppelpunkt nennt sich Initialisierungsliste. Damit kannst du verhindern, dass der Standardkonstruktor der Objekte aufgerufen wird und kannst stattdessen einen anderen benutzen (auch für die Vorfahrklasse). Funktionen kann man in der Initialisierungliste aber nicht (direkt) aufrufen (wäre mir jedenfalls neu).
-
Little Programmer schrieb:
Wenn ich einen Zeiger oder eine Referenz deklariere oder als Argument in einer Funktioen erwarte, sind dann folgende Varianten bedeutungsgleich?
Ja, das ist Geschmackssache.
Little Programmer schrieb:
Hinter dem ":" in Zeile 5, was darf da alles genau stehen? Soweit ich das jetzt verstanden habe, darf mit man dort Variablen mit der Schreibweise Variable(Wert) Werte zuordnen und beliebige Funktionen aufrufen. Wenn man dort aber alles darf, wieso macht man es dann nicht in den geschweiften Klammern?)
Diese Auflistung der Attribute (Membervariablen) einer Klasse ist die Initialisierungsliste. Dort kannst und solltest(!) Du allen Attributen einer Klasse einen Anfangswert zuweisen. Wenn Du es nicht machst, werden (wenn vorhanden) die Standardkonstruktoren der einzelnen Attribute aufgerufen.
Wenn Du die Initialisierungsliste nicht schreibst, wird sie also trotzdem erzeugt und du würdest doppelt die Attribute initialisieren, wenn Du es innerhalb der geschweiften Klammern machst.
Du kannst aber keine lokalen Variablen, die Du im Konstruktor verwendest dort initialisieren, sondern nur die Attribute der Klasse.
Referenzen (KlassenName&) und Paramterübergabe an die Basisklasse(n) kannst Du z.B. NUR in der Initialisierungsliste initialisieren.Also immer die Initialisierungsliste verwenden und die Attribute dort in der gleichen Reihenfolge, wie sie (im Header-File z.B.) deklariert wurden auflisten, da entscheidend ist, in welcher Reihenfolge sie deklariert wurden, und nicht in welcher Reihenfolge sie in der Initialisierungsliste auftauchen. Könnte zu ungewollten Effekten führen, wenn die Reihenfolge wichtig ist.
-
devkid schrieb:
Zur ersten Frage:
Die beiden Varianten sind bedeutungsgleich. Allerdings bevorzuge ich die Variante mit dem Asterisk (*) direkt vor dem Variablennamen, denn sonst könnte man leicht folgende (falsche) Schlussfolgerung ziehen:char* str1, str2; // str1 vom Typ char*, str2 vom Typ char; man denkt, beide seien vom Typ char* char *str1, *str2; // beide vom Typ char*Sehe ich auch so, auch wenn ich prinzipiell nichts davon halte in einer Zeile mehrere Variablen zu deklarieren.
devkid schrieb:
Zur zweiten Frage:
Hinter dem : kannst du durch Komma getrennt einerseits Membervariablen mit einem Wert (auch Rückgabewerte von Funktionen sind möglich) oder auch die Konstruktoren der Basis-Klassen (in deinem Beispiel könntest du auch noch... Testklasse () : ZweiteKlasse (parameter, fuer, Konstruktor, von, ZweiteKlasse) {}schreiben).Stimmt, das mit dem Konstruktor der Basisklasse habe ich völlig vergessen. Obwohl das ja wohl eigentlich mit die wichtigste Aufgabe ist
.
-
Ich glaube mit:
Little Programmer schrieb:
[...]Hinter dem ":" in Zeile 5, was darf da alles genau stehen? Soweit ich das jetzt verstanden habe, darf mit man dort Variablen mit der Schreibweise Variable(Wert) Werte zuordnen und beliebige Funktionen aufrufen[...]
meinte der Threadersteller sowas hier:
int GibMirFuenf() { return 5; } class Klasse { public: Klasse(): m_variable(GibMirFuenf()) { } private: int m_variable; };Und ja, solche Funktionsaufrufe funktionieren ;).
-
Vielen Dank für eure ganzen Antworten, jetzt ist mir das alles ein wenig klarer geworden :).