[C++] Objekte unbekannten Typs dynamisch erzeugen

BlackBox

Cadet 4th Year
Registriert
Sep. 2004
Beiträge
119
Hallo zusammen,

eine Frage zur dynamischen Erzeugung von Objekten in C++:

Gibt es eine Möglichkeit, ein Objekt eines beliebigen Typs zu erzeugen, wenn der Typ erst zur Laufzeit bekannt ist?
Was ich meine: ich habe einen Zeiger auf eine bestimmte Basisklasse. Diese hat mehrere Unterklassen, und ein Objekt so einer Unterklasse soll meinem Basisklassenzeiger zugewiesen werden. Es steht aber erst zur Laufzeit fest, welcher Basisklasse dieses Objekt angehört, also müsste ich mit switch/case Abfrage den Typ ermitteln und ein entsprechendes Objekt erzeugen, das ich dann dem Zeiger zuweise. Kann ich diese switch/case Abfrage irgendwie umgehen, damit nicht jede neu hinzugefügte Basisklasse eine Erweiterung des switch/case statements erforderlich macht?
 
mit virtuellen methoden sollte das gehen, kommt natürlich immer drauf an wie das design der klassen aussieht. ansonsten solltest du aber überlegen ob das sinnvoll ist. ich kenne nun dein problem und deinen code nicht genau, aber solche fälle hatte ich eigentlich noch nie. in der regel lies sich das mit templates ordentlich zur compile zeit machen, wie es sich für ein richtiges c++ programm gehört :P.
 
Was du anscheinend willst, ist das klassische Objekt-Fabrik-Problem.


Klassisches Beispiel:
Man speichert eine Grafik ab mit verschiedenen Objekten, die von Shape abgeleitet sind - z.B. Circle, Rectangular, Square, Triangle. Jedes dieser Objekte weiß wie es sich in eine Datei schreibt. Als erstes z.B. eine Zahl, was es ist. (1 für Circle etc.) Nun muss man beim Laden wieder dynamisch zuordnen, welches Objekt man erzeugen will, wenn man eine 1 liest. Das mit einem switch/case zu machen ist die denkbar schlechteste Variante. Da es in C++ auch keine virtuellen Konstruktoren gibt (C++ hat ein statisches Typsystem), muss man hier auf eine Objektfabrik zurückgreifen. Man hat eine Fabrik (ein Objekt einer Fabrik-Klasse), bei der man Fabrikfunktionen zusammen mit einem Kennzeichen registriert. Dann gibt es eine Methode in der Fabrik, der man nur ein Kennzeichen übergibt und die daraufhin einfach die registrierte Fabrikfunktion aufruft und das korrekte Objekt erzeugt und zurückgibt (die Objekte müssen dann natürlich alle die selbe Basisklasse haben).

Templates helfen hier übrigens garnicht weiter, da man hier dynamische Typisierung braucht, Templates aber ein statisches Konstrukt sind.

Beispiel:

Code:
class Base {};

typedef Base* (*FactoryFunc)();

class Factory
{
public:
  void register( char token, FactoryFunc f);
  Base* create( char token);
};

register merkt sich das Token zusammen mit der Funktion und speichert sie (z.B. in einer Map). Dann sucht create die passende Funktion zu dem Token raus, erzeugt das Objekt mit der registrierten Funktion und gibt es zurück. So kann man auch später zur Laufzeit noch bis dato unbekannte Klassen (bzw. Fabrikfunktionen) bei der Fabrik registrieren.

Hier kann man natürlich noch Templates ins Spiel bringen und die Basisklasse und den Tokentyp per Template konfigurierbar machen. Das Verhalten, wenn ein Token nicht registriert ist, ließe sich noch über Policies steuern.

Die Factory müsste natürlich noch einen Mechanismus zum Zerstören bereitstellen, da der Aufrufer von create nicht wissen kann, ob die Objekte vielleicht mit new, mit malloc oder mit einem eigenen Allokator erzeugt wurden und somit nicht einfach ein Delete auf den Zeiger machen kann.

Die Basisklasse muss natürlich auch mindestens einen virtuellen Destruktor bereitstellen.


Ich hoffe das hilft dir soweit.
 
Das mit der Objektfabrik würde mein Problem wunderbar lösen. Danke dir 7H3 N4C3R!
 
Zurück
Oben