String an einen Konstruktor übergeben
-
Ich bin es nochmal. Ich habe meine Headerdatei ein wenig erweitert, jedoch kommt bei der Kompilierung, wenn ich dieses File inkludieren möchte, ein Fehler, welchen ich gleich beschreiben werde. Zuerst hier mal meine Header-Datei:
#ifndef SPIELER_H #define SPIELER_H #include <string> class Spieler { public: Spieler(const string& n, const Color& c) : name(n), color(c) {} // line 19 Spieler(const Spieler& orig); virtual ~Spieler() {} enum Color {rot=1, gruen, blau}; string& getName() const { return name; } int getColor() const {return color; } // setter-methods void setName(string& n) { name=n; } void setColor(Spieler::Color& c) { color=c; } // Umleitung des Ausgabeoperators std::ostream& outputToStream(std::ostream& ostr) const; private: string name; // Name des Spielers Color color; Stein stein; Magnetstein mstein; }; std::ostream& operator<<(ostream& ostr, Spieler const& rhs); #endif /* SPIELER_H */
Die Fehlermeldung ist dann folgende:
In file included from main.cpp:11: Spieler.h:19: error: expected ',' or '...' before '&' token Spieler.h:19: error: ISO C++ forbids declaration of 'string' with no type Spieler.h:26: error: ISO C++ forbids declaration of 'string' with no type Spieler.h:26: error: expected ';' before '&' token Spieler.h:27: error: expected `;' before 'int' Spieler.h:31: error: 'string' has not been declared Spieler.h:39: error: 'string' does not name a type Spieler.h: In constructor 'Spieler::Spieler(int)': Spieler.h:19: error: class 'Spieler' does not have any field named 'name' Spieler.h:19: error: 'n' was not declared in this scope Spieler.h:19: error: 'c' was not declared in this scope Spieler.h: In member function 'void Spieler::setName(int&)': Spieler.h:31: error: 'name' was not declared in this scope Spieler.h: At global scope: Spieler.h:49: error: declaration of 'operator<<' as non-function Spieler.h:49: error: 'ostream' was not declared in this scope Spieler.h:49: error: 'ostr' was not declared in this scope Spieler.h:49: error: expected primary-expression before 'const'
Es geht siche rst einmal um den Fehler in Zeile 19. Was bedeutet dieser?
-
string liegt im Namespace std. Ersetze also
string
durchstd::string
.Tipp: Bei unerklärlichen Fehlermeldungen auch die vorherige(n) Zeile(n) betrachten.
-
Da sind noch viel mehr Sachen falsch, auch schon viel früher. Komisch, dass das keine Fehlermeldungen gibt. Ist das auch sicher die erste Fehlermeldung und der genaue Code?
1. Ein Include von ostream oder iosfwd fehlt
2. Magnetstein und Stein müssen irgendwo definiert werden oder ein entsprechender Header eingebunden werden.
3. Bevor du Color als Typen benutzt, muss es deklariert werden. Das heißt, deine Zeile 11 muss vor der ersten Benutzung von Color kommen.
4. string und ostream gehören zum Namespace std. Das hast du fast überall vergessen.
5. Zeile 13 widerspricht sich selbst. Willst du name nun ändern können oder nicht?
-
Okay, ich hatte vorher "using namespace std" im Code gehabt, es aber rausgenommen (hier gelesen) und dann natürlich vergessen, std:: überall vorzuschreiben.
Dass Stein und Magnetstein nicht kompiliert wurde, lag daran, dass auch ein include wohl fehlte.
Warum muss ich bei den getter-Methoden keine Referenz zurückgeben?
Also hier bei mir in Zeile 13std::string getName() const { return name; }
statt
std::string& getName() const { return name; }
Jedenfalls kommen nun keine Fehlermeldungen mehr
-
Weil eine Kopie erstellt diese dann zurückgegeben wird.
using namespace std; solltest du auf keinen Fall in Headern verwenden. Also dort immer std:: schreiben.
-
Wieso eigentlich? Wozu knapp 100 mal std:: schreiben, wenn man einmal using namespace std; tippt und dann auf ein paar Namen verzichtet?
Das ist extremer Mehraufwand dafür, dass der unwahrscheinliche Fall eintritt, dass etwas bereits in std definiert wurde.
Ich versteh das immer noch nicht wirklich warum ich das machen sollte.
-
Incocnito schrieb:
Wieso eigentlich? Wozu knapp 100 mal std:: schreiben, wenn man einmal using namespace std; tippt und dann auf ein paar Namen verzichtet?
Das ist extremer Mehraufwand dafür, dass der unwahrscheinliche Fall eintritt, dass etwas bereits in std definiert wurde.
Ich versteh das immer noch nicht wirklich warum ich das machen sollte.Du sollst using namespace nicht in die Header schreiben, weil es zu Namenskonflikten kommen kann.
Angenommen du tust es in deine Header. Dann inkludiert irgendwer deine Header. Dann erstellt er irgendetwas eigenes und nennt es so wie etwas im std::. Irgendwann bekommt er dann einen Fehler um die Ohren und weiß erstmal net warum... er kann ja nicht riechen, dass du using namespace std in deiner Header stehen hast.lg
-
Incocnito schrieb:
Wieso eigentlich? Wozu knapp 100 mal std:: schreiben, wenn man einmal using namespace std; tippt und dann auf ein paar Namen verzichtet?
Das ist extremer Mehraufwand dafür, dass der unwahrscheinliche Fall eintritt, dass etwas bereits in std definiert wurde.
Ich versteh das immer noch nicht wirklich warum ich das machen sollte.Verstehst du den Sinn von Namensräumen überhaupt? Denn damit sollte sich auch deine Frage klären.
-
Namensräume sind ja dazu da, um Namenskonfilkte zu vermeiden.
Sodass man, wenn man 2 mal eine Funktion mit dem selben Namen hat, sagen kann, welche benutzt werden soll. Anders geht das ja nicht.
Ist es aber wirklich so sinnvoll, sehr oft std:: zu tippen und dafür dann ein paar eigene Namen zu benutzen? Ich meine, wenn man selbst Funktionen definiert, die vielleicht schon in std drin sind, kann man ja seine eigenen in einen Namensraum packen. Damit ist eine Verwechslung auch ausgeschlossen, und man schreibt in dem Fall nur noch dann einen Namensraum vor etwas, wenn man wirklich seine eigene Funktion benutzen will, und wenn nicht, dann nicht. Damit erspart man sich das ewige std::., und kann trotzdem eigene Funktionen ohne Namenskonflikte verwenden.
Was seh ich da so falsch? Kann mich mal jemand aufklären warum meine Variante so unschön ist
-
In einem Header hast du keine Kontrolle darüber, in welchem Ausmaß das using wirkt.
// dein_header.h #include <string> using namespace std; string foo(); // anderer_header.h class string {}; // irgendeine_cpp.cpp #include "dein_header.h" #include "anderer_header.h" void bar() { string baz; // Welche Klasse string? }
-
Ach, was solls. Keine Lust auf streiten. Ich benutz std:: halt nur noch in Headern. Den Streit würde ich sowieso verlieren.
Eine Sache wär da aber noch:
Wenn ich in einer Header eine Klasse deklariere die viel mit cout macht, und dessen Methoden dann in der dazugehörigen .cpp definiere, kann ich dann
using std::cout;
schreiben oder ist das ebenso unschön?
-
Incocnito schrieb:
using std::cout;
schreiben oder ist das ebenso unschön?Kommt drauf an wo. In deiner cpp-Datei kannst machen was du willst, da kannste auch gerne globale Variablen und ähnliche Schweinereien benutzen.
Der Header aber ist das, was von anderen Programmierern benutzt wird, da hat man sich gefälligst zu benehmen und nur die Sachen zu deklarieren die dieser Header anbieten soll. Und ganz bestimmt soll man dort nicht den globalen Namensraum mit irgendwelchen Symbolen verseuchen die nicht ausdrücklich erwünscht sind.
-
Wenn man im Header einen eigenen Namensbereich für seine Klasse benutzt, so kann man dadrin dann aber auch einfach "using" verwenden:
// in header file #include <string> namespace MyNamespace { using std::string; class MyClass { string DoSomething(const string & str); // viele weitere Methoden mit "std::"-Klassen ... } }
Innerhalb des eigenen Namensbereiches kann man dann also einfach "string" benutzen, von außerhalb aber weiterhin "std::string"...
So gibt es dann auch keinen Konflikt mit anderen Header-Dateien.
P.S: Auf ein "using namespace std;" würde ich aber auch hier verzichten (nur das einbinden, was man auch wirklich benötigt!)
-
Incocnito schrieb:
Namensräume sind ja dazu da, um Namenskonfilkte zu vermeiden.
Nein, das ist nicht ihr einziger Anwendungszweck.
Um Namenskonflikte zu vermeiden, könnte man auch lediglich Präfixe nehmen.