Aufruf des Basisklassen-Konstruktors
-
Hallo.
Ich habe folgenden Fall:
Eine abgeleitete und auch deren Basisklasse erhalten einen String als Konstruktor-Parameter.class Parent { public: Parent(string) { ... } } class Child : public Parent { public: Child(string) { ... } }
Das Problem ist nun, dass der Parameter für den Konstruktor der Basisklasse erst im Konstruktor der abgeleiteten Klasse durch parsing gebildet wird. (Teilstring)
Wie rufe ich also den Konstruktor der Basisklasse im Körper des Konstruktors der abgeleiteten Klasse auf?
Um Inkonsistenzen zu vermeiden, hat die Basisklasse keinen Default-Konstruktor. (Außer dem der vom Compiler erzeugt wird.)
-
ZaHaDum1984 schrieb:
Wie rufe ich also den Konstruktor der Basisklasse im Körper des Konstruktors der abgeleiteten Klasse auf?
Hallo,
gar nicht. Das kann nicht funktionieren, da im Rumpf (der abgeleiteten Klasse sowieso) das Objekt schon konstruiert sein muss.
Überdenke besser das Design nochmal.
-
class Parent { public: Parent(string) { ... } } class Child : public Parent { public: Child(string v) : Parent(parse(v)) { ... } private: string parse( string ) {...} // oder als freie Funktion }
ZaHaDum1984 schrieb:
Um Inkonsistenzen zu vermeiden, hat die Basisklasse keinen Default-Konstruktor. (Außer dem der vom Compiler erzeugt wird.)
Wenn der Compiler einen generieren würde, hätte die Klasse auch einen.
-
Jockelx schrieb:
ZaHaDum1984 schrieb:
Wie rufe ich also den Konstruktor der Basisklasse im Körper des Konstruktors der abgeleiteten Klasse auf?
Hallo,
gar nicht. Das kann nicht funktionieren, da im Rumpf (der abgeleiteten Klasse sowieso) das Objekt schon konstruiert sein muss.
Überdenke besser das Design nochmal.Ich hatte auch schon daran gedacht hier Komposition oder Aggregation anstatt Vererbung einzusetzen.
Jedoch handelt es sich hier um eine Erweiterung der Funktionalität der Basisklasse, was logisch einer Vererbung entspricht. ("ist ein ..." und nicht "hat ein ...")
-
Und was spricht dagegen, es wie manni66 halt nicht im Rumpf sondern 'normal' in der Initialisierungsliste zu machen?
-
Jockelx schrieb:
Und was spricht dagegen, es wie manni66 halt nicht im Rumpf sondern 'normal' in der Initialisierungsliste zu machen?
Ich teste das gerade und melde mich dann wieder.
Ein wenig Geduld bitte.
-
Ok, ich bin nur so aufgeregt!
-
Jockelx schrieb:
Ok, ich bin nur so aufgeregt!kein Problem.
-
Es gibt da noch ein paar Fehlermeldungen, derer ich nicht Herr werde.
Hier der Code:
include/position.h
#ifndef POSITION_H #define POSITION_H 1 #include <vector> #include "bitboards.h" using namespace std; class Position : public Bitboards { private: string getPartString(const string, const string, const unsigned int); public: Position(string FEN) : Bitboards(getPartString(FEN, " ", 0)); }; #endif
src/position.cpp
#include "position.h" string Position::getPartString(const string fullString, const string delimiter, const unsigned int number) { vector<string> tokens; size_t prev = 0, pos = 0; do { pos = fullString.find(delimiter, prev); if (pos == string::npos) pos = fullString.length(); string token = fullString.substr(prev, pos-prev); if (!token.empty()) tokens.push_back(token); prev = pos + delimiter.length(); } while (pos < fullString.length() && prev < fullString.length()); return tokens[number]; } Position::Position(string FEN) : Bitboards::Bitboards(getPartString(FEN, " ", 0)) { ... }
make liefert folgendes output:
make -C build/64bit make[1]: Verzeichnis „/cygdrive/d/Repos/manticore/build/64bit“ wird betreten g++ -I ../../include -std=gnu++11 -m64 -D_REENTRANT -DVERSION=0.0.1 -D_FORTIFY_SOURCE=2 -DIS_64BIT -O3 -Wall -MD -MP -o position.o -c ../../src/position.cpp In file included from ../../src/position.cpp:1:0: ../../include/position.h: In Konstruktor »Position::Position(std::string)«: ../../include/position.h:16:62: Fehler: expected »{« at end of input Position(string FEN) : Bitboards(getPartString(FEN, " ", 0)); ^ ../../src/position.cpp: Im globalen Gültigkeitsbereich: ../../src/position.cpp:20:1: Fehler: Redefinition von »Position::Position(std::string)« Position::Position(string FEN) : Bitboards::Bitboards(getPartString(FEN, " ", 0)) ^ In file included from ../../src/position.cpp:1:0: ../../include/position.h:16:3: Anmerkung: »Position::Position(std::string)« wurde vorher hier definiert Position(string FEN) : Bitboards(getPartString(FEN, " ", 0)); ^ make[1]: *** [Makefile:15: position.o] Fehler 1 make[1]: Verzeichnis „/cygdrive/d/Repos/manticore/build/64bit“ wird verlassen make: *** [Makefile:2: 64bit] Fehler 2
Vermutlich etwas triviales, was ich selbst aber nicht sehe.
-
Ja, der Aufruf des Basis-Konstrukotrs gehört nur ins Cpp.
Ansonsten überleg dir mal, ob du nicht lieber const string**&** übergeben willst und wenn du dann noch lust hast, google mal, warum man namespaces nicht in headern öffnen sollte.
-
Jockelx schrieb:
Ja, der Aufruf des Basis-Konstrukotrs gehört nur ins Cpp.
Danke für den Hinweis.
Ich habe definitiv zu lange nicht mehr in C++ programmiert.
Jockelx schrieb:
Ansonsten überleg dir mal, ob du nicht lieber const string& übergeben willst
Das werde ich natürlich machen. Dies is bisher nur ein erster schnell geschriebener Entwurf.
Jockelx schrieb:
google mal, warum man namespaces nicht in headern öffnen sollte.
Interessant, so hat man mir das im Grundstudium beigebracht. Danke für den Hinweis.