Initialisierungslistenproblem
-
Hallo leute, ich dachte eigentlich ich nehme eine Initialisierungsliste, um zB Refrenzen und const im Konstruktor zu initialisieren!
ABER nun hab ich das mal probiert, ud es geht nicht....
class Test { public: Test(int a):zahl(a),zahl2(a),zahl3(a){ergebniss=a*a;} int GetResult(); int GetZahl(int a); private: int zahl; int& zahl2; const int zahl3; int ergebniss; }; int Test::GetResult() { return ergebniss; } int Test::GetZahl(int a) { if (a==1) return zahl; if (a==2) return zahl2; if (a==3) return zahl3; }
Fehlermeldungen:
[C++ Fehler] Unit1.cpp(15): E2359 Referenzelement 'Test::zahl2' wurde mit einem Nicht-Referenz-Parameter initialisiert [C++ Warnung] Unit1.cpp(38): W8070 Funktion sollte einen Wert zurückgeben
was hab ich falsch gemacht??
-
Du initialisierst die Referenz mit einer lokalen Variable, das ist das Problem. a existiert nicht mehr, wenn der Konstruktor beendet ist, also wohin zeigt dann die Referenz?
Dass das ein Fehler ist, erstaunt mich allerdings, ich hätte nur mit einer Warnung gerechnet.
-
Wellness schrieb:
was hab ich falsch gemacht??
Fehlermeldungen lesen! 'int a' ist keine Referenz.
if (a==1) return zahl; if (a==2) return zahl2; if (a==3) return zahl3;
Schon mal was von Arrays gehört?
-
groovemaster schrieb:
Wellness schrieb:
was hab ich falsch gemacht??
Fehlermeldungen lesen! 'int a' ist keine Referenz.
ja stimmt, wenn ich aber jetzt:
Test(int& a):zahl(a),zahl2(a),zahl3(a){ergebniss=a*a;}
kommt der fehler nich mehr, aber dann kann ich dies nichmehr ausführen..
int main(int argc, char* argv[]) { Test test = new Test(10); <<-- das geht dann logischerweise nich mehr int a=test->GetZahl(1); int b=test->GetResult(); cout<<"Zahl: "<<a<<endl; cout<<"Ergebniss: "<<b<<endl;
also wie koennte ich das problem beheben?
-
Wellness schrieb:
also wie koennte ich das problem beheben?
Nicht Test(10) benutzen. Wie soll denn ein Literal an eine Referenz gebunden werden?
-
hm...und wie dann?
Sorry bin anfänger noch im bereich c++!
Hoffe kannst mir das nochmal erklären!
-
Eine Referenz ist ein anderer Name für ein bereits bestehendes Objekt. 10 ist kein Objekt, sondern ein Literal, darum kannst du zu 10 keine Referenz erzeugen. Du brauchst für den Konstruktoraufruf eine echte Variable:
int x = 10; Test* test = new Test(x)
-
ja stimmt,. so funktioniert es auch!
Aber gibt es da noch einen besseren weg?
und wie könnte ich das:
groovemaster schrieb:
Wellness schrieb:
was hab ich falsch gemacht??
Fehlermeldungen lesen! 'int a' ist keine Referenz.
if (a==1) return zahl; if (a==2) return zahl2; if (a==3) return zahl3;
Schon mal was von Arrays gehört?
am besten umsetzten?
-
Bei deinen drei Vergleichen ist es noch nicht so schlimm, aber was machst du, wenn du z.B. 20 (oder 200) Werte hast, die du mit dem Paramter vergleichen willst?
Für diesen Fall verwendet man normalerweise Arrays.
// v ist ein int-Array, welches bei dir als Private-Element deklariert ist int Test::GetZahl(int a) { for(unsigned int i = 0; i < (sizeof(v) / sizeof(v[0])); ++i) if(a == v[i]) return v[i]; // Wurde a an der i-ten Position von v gefunden? => zurückgeben return -1; // Hier einen Fehlerwert zurückgeben, da a im Array v nicht gefunden wurde. // (Am besten nicht -1, da -1 ja auch als "regulärer" Wert im Array vorkommen kann) }
Zu Arrays siehe am besten auch in der C++-FAQ nach (Thread: Arrays und Pointer).
Caipi
-
ja danke, mit dem array schau ich mir mal an!
Und nun nochmal dazu:
MFK schrieb:
int x = 10; Test* test = new Test(x)
kann man das auch anders machen, oder muss ich das so schrieben, wenn ich eine referenz initialisiere?
-
MFK schrieb:
10 ist kein Objekt, sondern ein Literal, darum kannst du zu 10 keine Referenz erzeugen.
Das kannst du, oder besser der Compiler, schon. Nur brauchst du dafür eine const-Referenz. Dann kann nämlich implizit ein temporäres Objekt erstellt werden. Nur ist dabei Vorsicht geboten. Wenn der ctor Aufruf beendet ist, wird auch das temporäre Objekt zerstört. Wenn innerhalb der Klasse dieses aber weiterhin referenziert wird, hantierst du mit totem Fleisch.
@Wellness
Das mit dem Array hab ich eigentlich anders gemeint als Caipi.
Wenn du drei Variablen hast, zahl, zahl2 und zahl3, dann kannst du dafür genauso gut ein Array verwenden.int zahlen[3];
Dabei entspricht
zahl -> zahlen[0] zahl2 -> zahlen[1] zahl3 -> zahlen[2]
Und anstatt deiner if-Abfragen
if (a==1) ... if (a==2) ... if (a==3)
nimmst du a einfach als Index (entsprechend von 0 bis 2) und greifst dann damit auf das Array zu
return zahlen[a];
Das funktioniert aber halt nur, wenn alle Werte im Array vom gleichen Typ sind. Da du aber int, int& und const int verwendest, weiss ich nicht ob du damit was anfangen kannst. Es war auch mehr als Denkanstoss gedacht, da mir deine bisherige Vorgehensweise etwas seltsam vorkommt. Was aber nichts heissen muss.
nochwas:
Du legst deine Instanz dynamisch an. Ist das notwendig? Der Normalfall sollte eher sein, dass du dafür automatischen Speicher benutzt (sprich Stack). Nur wenn es Gründe dafür gibt, zB grosse Mengen an Speicher oder ein Weiterleben der Instanz nach Verlasssen des Scopes, solltest du auf dynamischen Speicher zurückgreifen.
-
Ja das wollte ich, weil ich ja etwas teste...
werd es dann mal stackmässig testen
Danke erstmal!