Die korrekte Initialisierung von Objekten

Veröffentlicht: 27. Jan 2002 | Aktualisiert: 15. Jun 2004

Von Paul DiLascia

In C++ steht Ihnen zwar nicht die statische Initialisierung von Arrays zur Verfügung, aber Sie können Array-Elemente über beliebige Konstruktoren initialisieren.

Diesen Artikel können Sie hier lesen dank freundlicher Unterstützung der Zeitschrift:

Bild01

Frage

Wie kann ich in einer Klasse, die ich geschrieben habe, eine Datentabelle initialisieren? In C kann ich zum Beispiel folgendermaßen ein Array mit structs initialisieren:

struct MYSTRUCT { 
    int x,y,z; 
}; 
MYSTRUCT table[] = { 
    { 1,2,3 }, 
    { 4,5,6 }, 
    ... // und so weiter 
};

Handelt es sich bei MYSTRUCT aber nicht um eine struct, sondern um eine C++-Klasse, wirft der Compiler Fehlermeldungen aus. Mir scheint dies eine Schwäche von C++ zu sein.

Antwort

Nun, das hängt wohl von der Betrachtungsweise ab. Einer der Vorteile von C++ ist, dass es den Entwickler dazu zwingt, die vorgeschriebenen Wege zu gehen. So hasst C++ es zum Beispiel, ohne Konstruktoraufruf Objekte zu bauen. Deswegen können Sie die Instanz einer Klasse auch nicht mit rohen Daten initialisieren, sei es direkt oder in Form eines Arrays. Die Konstruktoren haben die Aufgabe, für die korrekte Initialisierung jedes Objekts zu sorgen, und zwar unabhängig davon, ob man die Objekte nun auf dem Programmstapel anlegt, im Freispeicher (heap) oder als Element eines statischen Arrays. Sich mit den Rohdaten um den Konstruktor herumzudrücken, ist einfach tabu. Es ist aber nicht so, dass man kein statisches Array mit Objekten anlegen und mit Daten initialisieren könnte. Das geht durchaus. Aber nur mit dem Aufruf des zuständigen Konstruktors.

class CFooble { 
    int x,y,z; 
public: 
    CFooble(int xx, int yy, int zz) 
        : x(xx),y(yy),z(zz) { ... } 
    CFooble(int i) { x=y=z=i; } 
}; 
CFooble table[] = { 
    CFooble(1,2,3), 
    CFooble(4,5,6), 
    CFooble(0),    // jeder Konstruktor tut's 
};

Im Listing L1 finden Sie ein vollständiges Beispiel, das sich kompilieren lässt. In C++ können Sie die Elemente eines Arrays mit jedem Konstruktor der betreffenden Klasse initialisieren. C++ greift sogar zum Standardkonstruktor, wenn zusätzliche Elemente ohne explizite Initialisierer zu initialisieren sind. Meiner Ansicht nach ist das eine Verbesserung und keine Schwäche!

L1 fooble.cpp zeigt die Initialisierung eines Arrays

///////////////////////////////////////////////////////// 
// MSDN  -  May 2000 
// Sofern dieser Code funktioniert, stammt er von  
//   Paul DiLascia. 
// Falls nicht, weiß ich auch nicht, wer ihn geschrieben 
//  hat. 
// Lässt sich mit Visual C++ 6.0 kompilieren, läuft unter 
// Windows 98 und vermutlich auch unter Windows NT. 
// 
// StaticClassArray  -  zeigt die Initialisierung eines 
// statischen Arrays mit C++-Objekten. 
// Kompilieren mit: 
// 
//    cl fooble.cpp 
// 
#include <stdio.h> 
////////////////// 
// Typische Beispielklasse mit drei Datenelementen... 
// 
class CFooble { 
protected: 
   int x,y,z; 
public: 
   // ... zwei Konstruktoren... 
   CFooble(int i) { x=y=z=i; } 
   CFooble(int xx, int yy, int zz) : x(xx),y(yy),z(zz)  
      { } 
   // ... einer print-Funktion... 
   void print() { 
      printf("CFooble at %p: (%d,%d,%d)\n",  
         this, x, y, z); 
   } 
   // ... und einer Funktion, die auf "Leere" testet. 
   int IsEmpty() { 
      return x==0 && y==0 && z==0; 
   } 
}; 
#ifdef NEVER 
// Das darf nicht funktionieren - Sie können keine C++- 
// Objekte mit "rohen" Daten initialisieren! 
CFooble table[] = { 
   { 1,2,3 }, 
   { 4,5,6 }, 
   { 0,0,0 } 
}; 
#endif 
// Und so wird ein Array mit Objekten initialisiert: 
CFooble table[] = { 
   CFooble(1,2,3), 
   CFooble(4,5,6), 
   CFooble(0), // Man darf auch den Konstruktor wechseln. 
}; 
void main() 
{ 
   for (CFooble* pc=table; !pc->IsEmpty(); pc++) { 
      pc->print(); 
   } 
}