enums in Konstruktoren verwenden
-
Hallo!
Ich habe eine Klasse erstellt, die einen enum "Color" enthaelt. Im Konstruktor dieser Klasse soll ein Argument übergeben werden, welches dann auf ein Attribut des enums zugewiesen werden soll.Was muss ich im Hauptprogramm dem Konstruktor uebergeben?
Hier mal der Code:class Spielstein { public: virtual ~Spielstein() {} virtual int getColor() { return farbe; } enum Color {grau=0, rot,blau,gelb}; protected: Color farbe; }; class Stein : public Spielstein { public: Stein(???) { farbe=???;} virtual ~Stein() {} };Dies sind meine beiden Klassen.
Und im Hauptprogramm moechte ich dann ein Objekt der Klasse Stein erstellen.
Ungefaehr so:int main(int argc, char** argv) { Stein s=Stein(rot); cout << s.getColor() << endl; return 0; }Ich hoffe, ihr koennt mir dabei helfen

-
Spielstein::rot
-
class Stein : public Spielstein { public: Stein(Spielstein::Color p_color) : farbe(p_color) {} virtual ~Stein() {} };
-
Übrigens solltest du Funktionen nur virtuell machen, wenn du auch vorhast, sie in abgeleiteten Klassen neu zu definieren (mit Ausnahme des Destruktors, welcher für polymorphe Zerstörung notwendig ist). Hingegen reicht in der abgeleiteten Klasse der compilergenerierte Destruktor, du musst ihn nicht nochmals selbst definieren.
Und das
=0im ersten Enumerator ist auch unnötig, da der erste Enumerator implizit immer Null ist. Abgesehen davon, dass die eigentlichen Zahlenwerte meist irrelevant sind.
-
Also wenn ich in einer Basisklasse eine Funktion definiert habe, muss ich davor nicht virtual schreiben, wenn ich diese Funktion in der Unterklasse nur benutzen möchte, wie sie in der Oberklasse definiert ist, richtig?
Gut, hatte gedacht, man müsste immer virtual schreiben, wenn man die Funktionen quasi übernehmen möchte.
Danke
-
virtual brauchst du, wenn du Zeiger auf Objekte einer abgeleiteten Klasse in Zeigern auf Objekte der Basisklasse speichern willst.
Beispiel: http://codepad.org/A28Ku77O
Sieh dir dir Ausgaben an, du wirst sehen, dass bei der letzten Ausgabe "Hello World! Hello World!" und nicht "Hallo Welt! Hallo Welt!" erscheint, weil virtual nicht verwendet wurde
-
314159265358979 schrieb:
virtual brauchst du, wenn du Zeiger auf Objekte einer abgeleiteten Klasse in Zeigern auf Objekte der Basisklasse speichern willst.
Unsinn.
virtualhat nichts mit Zeigern zu tun.#include <iostream> struct base { void foo() { std::cout << "base::foo" << std::endl; } virtual void bar() { std::cout << "base::bar" << std::endl; } }; struct derived : base { void foo() { std::cout << "derived::foo" << std::endl; } void bar() { std::cout << "derived::bar" << std::endl; } }; int main() { std::cout << "derived d" << std::endl; derived d; d.foo(); d.bar(); std::cout << "\nbase& rb = d" << std::endl; base& rb = d; rb.foo(); rb.bar(); std::cout << "\nbase b" << std::endl; base b; b.foo(); b.bar(); }derived d derived::foo derived::bar base& rb = d base::foo derived::bar base b base::foo base::barWie man sieht keine Zeiger. Bei
virtualgeht es nur um die Polymorphie. Beivirtualbei Funktionen geht es nur darum, welche Funktion aufgerufen werden soll. Soll die Funktion aufgerufen werden, welche zum statischen Typ der Variable gehört (sieherb.foo()-> statischer Typ vonrbistbase) oder soll die in der Hierarchie des Objektes am spezialisiertesten Funktion zum Einsatz kommen (sieherb.bar()-> das Objekt ist tatsächlich vom Typderived, daher ist die spezialisierteste Funktionderived::bar). Dabei genügt es, wennvirtualeinmal in der Basisklasse hingeschrieben wurde. Meistens schreibt man abervirtualtrotzdem hin, um es zu verdeutlichen, dass es sich um eine virtuelle Funktion handelt, bzw. im neuen C++ Standard kann man dazuoverridehinter der Funktion hinschreiben.Übrigens:
base b2 = d; // Das ist eine Kopie! // b2 ist ein Objekt vom Typ base, alle Informationen über derived gehen // bei der Kopie verloren. Sowas nennt man auch Slicing. b2.foo(); b2.bar(); // erzeugt dasselbe Ergebnis wie beim Beispiel mit b! // base::foo // base::barbase* pb = &d; pb->foo() pb->bar(); // verhält sich wie das Beispiel mit rb. // base::foo // derived::barEs geht somit über Zeiger und Referenzen, da dort das Objekt nicht kopiert wird. Es ändert sich nur der statische Typ der Variable, aber nicht der tatsächliche Typ des Objektes.
Grüssli
-
Das habe ich doch gesagt, wenn auch weniger ausführlich, abgesehen davon, dass ich Referenzen nicht erwähnt habe.
-
314159265358979 schrieb:
Das habe ich doch gesagt, wenn auch weniger ausführlich, abgesehen davon, dass ich Referenzen nicht erwähnt habe.
Nein, du hast folgendes gesagt:
struct base { void foo() { }; }; struct derived { }; int main() { derived d; base* p = &d; }Dafür bräuchte man
virtual. Wie du siehst, ist das aber hinten und vorne nicht der Fall. Womöglich hast du das gemeint, was ich geschrieben habe, aber das hast du nicht hingeschrieben. Was du hingeschrieben hast stimmt einfach nicht.Grüssli
-
Ich sagte für das erwünschte Verhalten braucht man virtual, und das ist richtig.
-
314159265358979 schrieb:
Ich sagte für das erwünschte Verhalten braucht man virtual, und das ist richtig.
Ich will ja nicht pingelig sein, aber das ging aus deinem Beitrag hinten und vorne nicht raus. Geschrieben hast du völlig was anderes. Vergiss all dein Wissen über
virtualund Polymorphie in C++ und liess dann nochmals deinen Beitrag. Würdest du als Anfänger daraus wirklich schlau werden? Ich habe so meine Zweifel
Grüssli
-
Du hast Recht, wenn du sagst, dass meine Erklärung scheiße ist. Richtig ist sie trotzdem.
-
Dann erklär mir mal, wieso der folgende Satz richtig sein soll:
314159265358979 schrieb:
virtual brauchst du, wenn du Zeiger auf Objekte einer abgeleiteten Klasse in Zeigern auf Objekte der Basisklasse speichern willst.
Ich füge in diesem Satz ein Wort ein und dann wäre er richtig:
virtual brauchst du nicht, wenn du Zeiger auf Objekte einer abgeleiteten Klasse in Zeigern auf Objekt der Basisklasse speichern willst.Es ist nicht nur scheisse erklärt, sondern der Satz stimmt so auch gar nicht.
Grüssli
-
Dass da implizit steht "wenn du dieses Verhalten haben willst", habe ich vorrausgesetzt.
Mir aber auch latte, erklärs ihm einfach so, wie du es für richtig hältst.
-
Also ohne die Erklärung mit den Beispielen hätte ich ehrlich gesagt deinen Satz nicht ganz verstanden

Wie dem auch sei, danke für die Erklärung zur Benutzung des virtuals, auch wenn das nicht das Hauptthema war. Beides ist jetzt aber auch erklärt und hoffentlich verstanden

-
Manchmal glaube ich es gibt hier zwei User mit dem (annähernd) gleichen Namen
314159265358979 oder so...
Einer schreibt teilweise echt kompetente Beiträge und einer behauptet Mist
und versucht ihn dann krampfhaft als richtig zu verkaufen.
-
Ich habe noch einmal eine Frage bzw. ein Problem mit enums.
Ich habe in einer Klasse ueber dem Konstruktor ein enum definiert, welches "Position" heißt. Die Klasse besitzt ein Attribut mit dem Typ dieses enums.Wenn ich aber in einer Methode der Klasse auf dieses Attribut zugreifen will bzw. es setzen möchte, kommt ein Fehler.
Hier mal die Klasse: (nur das Nötige)
class Spielbrett { public: enum Position { normal=0, links=90, kopf=180, rechts=270 }; Spielbrett() { // Initialisiere das Spielbrett init(); } ~Spielbrett() { } // destructor void init(); private: Position pos; };Und hier ist die .cpp-Datei mit einer Methode:
#include "Spielbrett.h" #include <iostream> using namespace std; void Spielbrett::init() { /* Zeile 26 */ pos=Position::normal; }Fehler ist:
Spielbrett.cpp: In member function 'void Spielbrett::init()': Spielbrett.cpp:26: error: 'Position' is not a class or namespaceDabei ist doch Position ein enum der Klasse. Was ist falsch?
-
pos = normal;
-
Ach, ich bin mal wieder auf den Kopf gefallen! D.h., wenn ich auf ein enum zugreifen will, muss ich davor nicht den enum-typen schreiben. Da hat mich wohl etwas anderes durcheinander gebracht.
Danke sehr!
-
In C++0x gibt es
enum classbzw.enum struct, mit denen du das musst.Vorher verwendet man oft so ein Idiom, um qualifiziert auf die Enums zugreifen zu können:
namespace Position { enum Type { // Enumeratoren hier }; }