C++ Klasse zur Laufzeit aussuchen

Gast #2590375
Lesenswert?

Hallo Knobler,

ich möchte zur Laufzeit Klassen instanziieren, wobei erst zur Laufzeit 
anhand einer Konfigurationsdatei bekannt ist welche das konkret sein 
sollen:
1
class Fahrzeug
2
{
3
};
4

5
class Fahrrad: public Fahrzeug
6
{
7
};
8

9
class Auto: public Fahrzeug
10
{
11
};

Die Konfigurationsdatei könnte wie folgt aussehen:
1
config = {"Auto", "Fahrrad", "Fahrrad"};

Nun möchte ich natürlich sowas wie
1
if value=="Fahrrad"
2
  objlist.add(new Fahrrad);
3
else if value=="Auto"
4
  objlist.add(new Auto);
vermeiden, sondern irgendwie automatisiert die richtigen Objekte 
erzeugen.

Weiterhin soll es die Möglichkeit geben dass beim Anlegen eines Objektes 
(z.B. eines Autos) selbiges feststellen kann dass es nicht vollständig 
konfiguriert werden kann (z.B. weil in der config Datei das 
Nummernschild nicht gesetzt ist), und das Objekt gleich wieder zerstört 
wird.

Wie macht man sowas am besten?

Gruß
Werner
#2590410
Lesenswert?

Werner schrieb:
> sondern irgendwie automatisiert die richtigen Objekte erzeugen.

Schau Dir mal das Factory Pattern an:
http://en.wikipedia.org/wiki/Factory_pattern

> Weiterhin soll es die Möglichkeit geben dass beim Anlegen eines Objektes
> (z.B. eines Autos) selbiges feststellen kann dass es nicht vollständig
> konfiguriert werden kann (z.B. weil in der config Datei das
> Nummernschild nicht gesetzt ist), und das Objekt gleich wieder zerstört
> wird.

Warum? Auch in der realen Welt kann ein Auto ohne Nummernschild 
existieren. In der Software würde man ein solches Objekt anlegen, und 
sein entsprechendes Attribut (automobil->nummernschild) auf einen 
definierten "undefiniert" :-) Wert setzen.
Nur weil ein Attribut beim Anlegen des Objekts nicht definiert ist, 
heißt das ja nicht, dass es zur Laufzeit niemals dazu kommen kann. Das 
Auto wird vielleicht doch noch zugelassen, oder umgemeldet ;-)
Gast #2590526
Lesenswert?

Danke für die schnellen Antworten!

>Warum?

Weil ich natürlich keine Autos und Fahrräder implementiere, sondern 
Objekte die im übertragenem Sinne unbedingt ein Nummernschild brauchen. 
Die Klasse müsste ganz korrekt heißen 
"AutoMitWelchemEsBeiEinerVerkehrskontrolleZuKeinerleiProblemenKommt" ;-)

>Dazu braucht jede Klasse eine factory (oder virtueller Konstruktor),
>außerdem muß sich jede abgeleitete Klasse irgendwo anmelden
Ok, d.h. ich baue mir eine Form von einer Liste (map) in der meine 
config Namen ("Fahrrad", "Auto") mit den entsprechenden abgeleiteten 
Klassen verknüpft sind. In dieses Listenobjekt baue ich eine Methode ein 
der ich den Namen übergebe, und bei einem Match wird in dieser Methode 
der virtuelle Konstruktor aufgerufen. Wozu brauche ich in diesem Fall 
dann noch den virtuellen Konstruktor, ich könnte ja dann gleich den 
normalen Konstruktor aufrufen?
Und wie könnte ich meine Klassen in einer Liste registrieren, solange 
nichts instanziert wird, passiert ja auch nichts...

Gruß
Werner
#2590532
Lesenswert?

Werner schrieb:

>>Dazu braucht jede Klasse eine factory (oder virtueller Konstruktor),
>>außerdem muß sich jede abgeleitete Klasse irgendwo anmelden
> Ok, d.h. ich baue mir eine Form von einer Liste (map) in der meine
> config Namen ("Fahrrad", "Auto") mit den entsprechenden abgeleiteten
> Klassen verknüpft sind.

Eigentlich nicht mit der Klasse an sich, sonder mit einer Funktion, die, 
wenn man sie aufruft, ein entsprechendes Objekt erzeugt und 
zurückliefert.

Diese Funktion nennt man den 'virtuellen Konstruktor'.
#2590574
Lesenswert?

Werner schrieb:

> Weil ich natürlich keine Autos und Fahrräder implementiere, sondern
> Objekte die im übertragenem Sinne unbedingt ein Nummernschild brauchen.
> Die Klasse müsste ganz korrekt heißen
> "AutoMitWelchemEsBeiEinerVerkehrskontrolleZuKeinerleiProblemenKommt" ;-)

automobil->fahrer->setPromillewert(NUR_EIN_BIER_EHRLICH);

Hier ist ein Beispiel zum virtuellen Konstruktor:
http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Virtual_Constructor
Gast #2590705
Lesenswert?

>Am besten ein Beispiel studieren.

Das versuche ich gerade, z.B. das hier:

http://de.wikipedia.org/wiki/Fabrikmethode#Ein_Beispiel_in_C.2B.2B

Ich schaffe es nicht das ganze auf meine Problemstellung zu übertragen, 
und ich sehe in diesem Beispiel weit und breit keine statischen 
Methoden.

Muss ich meine Problemstellung so aufbauen?
1
class Fahrzeug
2
{
3
  virtual Fahrzeug* Create(void) = 0;
4
};
5

6
class Fahrrad: public Fahrzeug
7
{
8
//ist das nun eine factory method??!
9
  virtual Fahrzeug* Create(void) {return new Fahrrad};
10
};
11

12
class Auto: public Fahrzeug
13
{
14
//ist das nun eine factory method??!
15
  virtual Fahrzeug* Create(void) {return new Auto};
16
};

Die Create Methode kann ich ja nun nicht aufrufen, da es noch nicht mal 
ein Objekt gibt?
#2590720
Lesenswert?

Werner schrieb:
> Die Create Methode kann ich ja nun nicht aufrufen, da es noch nicht mal
> ein Objekt gibt?

Falsches Pattern.

eher sowas:
1
class base_constructor_func {
2
public:
3
  virtual Fahrzeug * create()=0;
4
};
5

6
template <class XYZ>
7
class constructor_func: public base_constructor_func {
8
public:
9
  Fahrzeug * create() { return new XYZ; } // oder "operator()()"
10
};
11

12

13
std::map<std::string, base_constructor_func*> constructors;
14

15
...
16
constuctors["Auto"]=new constructor_func<Auto>();
17
constuctors["PKW"]=new constructor_func<Auto>();
18
constuctors["Fahrrad"]=new constructor_func<Fahrrad>();
19
constuctors["LKW"]=new constructor_func<Lastwagen>();
20

21

22
...
23

24
Fahrzeug * neues_fahrzeug=constructors[configfile.xyz]->create();

Ach ja, die Pointer in der map sind nicht unbedingt guter Stil. Ggfs. 
shared_ptr oder sowas stattdessen verwenden.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren