class member initialization
-
Vielen Dank, genau das habe ich gesucht.
Schönen Tag noch!
-
Du möchtest oder musst vermutlich "Data-Encapsulation" zu betreiben! (Lob)
Dann musst du alle Attribute per private schützen und nur über entsprechende public-Methoden den
Zugriff gewähren.Wenn alle Instanzen deiner Klasse einen SIZE=10 besitzen sollen UND sich dieser nicht mehr ändern soll,
würde ich das Attribut so setzen:static const int SIZE=10;
die Sache static const Variablen inititieren war glaub ich etwas tricky... macht man die in der Klasse oder ausserhalb der Klasse?
-
template<typename T> class container { T* m_array; const std::size_t m_size; public: explizit container(std::size_t size) : m_size(size), m_array(new T[size]) {} ~container() { delete [] m_array; } };wobei dann die Frage ist, wofür du überhaupt noch dynamische Arrays nutzt?
-
gorgoyle schrieb:
die Sache static const Variablen inititieren war glaub ich etwas tricky... macht man die in der Klasse oder ausserhalb der Klasse?
Mit ganzzahligen Konstanten kannst Du es in der Klasse machen – falls Dein Compiler modern genug ist. Für andere Werte verlagert man die Definition (NICHT aber die Deklaration) nach außerhalb der Klasse.
struct Test { // Deklaration. static std::string const cstr; }; // Definition. KEIN 'static'-Schlüsselwort: std::string const Test::cstr = "Hallo";
-
Für andere Werte verlagert man die Definition (NICHT aber die Deklaration) nach außerhalb der Klasse.
Das ist falsch. Auch statische, konstante, integrale Objekte einer Klasse müssen definiert werden. Nur die Initialisierung kann sich in dem Fall in der Klasse befinden, um das Objekt als constant expression nutzen zu können.
If a static data member is of const integral or const enumeration type, its declaration in the class
definition can specify a constant-initializer which shall be an integral constant expression (5.19). In that
case, the member can appear in integral constant expressions. The member shall still be defined in a name-
space scope if it is used in the program and the namespace scope definition shall not contain an initializer.
-
Freundlich schrieb:
Für andere Werte verlagert man die Definition (NICHT aber die Deklaration) nach außerhalb der Klasse.
Das ist falsch. Auch statische, konstante, integrale Objekte einer Klasse müssen definiert werden. Nur die Initialisierung kann sich in dem Fall in der Klasse befinden, um das Objekt als constant expression nutzen zu können.
Hmm, Mist. Mein Compiler braucht die Extra-Definition nicht. Wie soll das denn in Code aussehen? So?
struct test { static const int i = 1; }; const int test::i;(Funktioniert. Wunderbar. Aber die letzte Zeile ist im aktuellen GCC und VC++ überflüssig.)
-
(D)Evil schrieb:
template<typename T> class container { T* m_array; const std::size_t m_size; public: explizit container(std::size_t size) : m_size(size), m_array(new T[size]) {} ~container() { delete [] m_array; } };Ohoh, das ist nicht gut. Warum? naja, es könnte jemand auf die Idee kommen, in der Initialisierungsliste an zweiter Stelle
m_array(new T[size])zu schreiben. Na und? And we enter the dark, dusty realms of Undefined Behaviour...
Folgendes passiert: Der Compiler initialisiert Klassenmember in der Reihenfolge ihrer Dekaration, und nicht in der Reihenfolge der Initialisierungsliste. Soll heißen, hier würde dasm_array(new T[m_size])vor demm_size(size)ausgeführt, obwohl es dahinter steht. Und da m_size also noch nicht initialisiert ist, ist die Größe des Arrays undefiniert. Von daher sollte man immer die Initiailisierungsliste in gleicher Reihenfolge wie die Deklarationen schreiben, um so subtile Fehler zu vermeiden und sich stundenlanges Bugtracking zu sparen.
-
Konrad Rudolph schrieb:
Freundlich schrieb:
Für andere Werte verlagert man die Definition (NICHT aber die Deklaration) nach außerhalb der Klasse.
Das ist falsch. Auch statische, konstante, integrale Objekte einer Klasse müssen definiert werden. Nur die Initialisierung kann sich in dem Fall in der Klasse befinden, um das Objekt als constant expression nutzen zu können.
Hmm, Mist. Mein Compiler braucht die Extra-Definition nicht. Wie soll das denn in Code aussehen? So?
struct test { static const int i = 1; }; const int test::i;(Funktioniert. Wunderbar. Aber die letzte Zeile ist im aktuellen GCC und VC++ überflüssig.)
Compiler sind bei solchen Dingen häufig nachsichtig, und Verletzungen der ODR müssen im Allgemeinen nicht diagnostiziert werden. Eine fehlende Definition wird für gewöhnlich frühestens beim Linken erkannt - aber nur dann, wenn tatsächlich eine Referenz auf das jeweilige Symbol existiert, nicht schon dann, wenn eine solche Referenz bloß existieren könnte. Dem Compiler steht es frei, solche Referenzen zu eliminieren, indem z.B. Ausdrücke bereits beim Compilieren ausgewertet werden, in solchen Fällen wird das Auslassen der Definition dann nicht diagnostiziert werden. Umgekehrt ist der Compiler aber nur dort verpflichtet, Ausdrücke beim Compilieren auszuwerten, wenn die Sprache an dieser Stelle einen konstanten Ausdruck erwartet. In allen anderen Fällen ist der Compiler völlig frei - und ein Programm ist nur dann konform, wenn es mit jeder in diesen Grenzen denkbaren Auswertungsentscheidung des Compilers funktioniert. Mithin ergibt sich Folgendes:
1. Eine integrale statische Memberkonstante einer Klasse kann bereits bei ihrer Deklaration initialisiert werden (es ist dann trotzdem nur eine Deklaration).
2. Jede folgende Verwendung des Wertes dieser Konstanten ist ein konstanter Integraler Ausdruck.
3. Eine Definition der Konstanten ist nur dann nicht erforderlich, wenn der Wert in einem Ausdruck verwendet wird, und an der Stelle ein konstanter Ausdruck stehen muss.
Zum Beispiel:struct Foo { static const int bar = 42; char x[bar]; // erfordert keine Definition void f(int y = bar); // erfordert Definition (wenn irgendwo mit Defaultargument aufgerufen) void g() { char* p = new char[bar]; // erfordert Definition char* q = new (char[bar]); // erfordert keine Definition char (*r)[bar] = new char[10][bar]; // erfordert keine Definition bar; // erfordert Definition &bar; // erfordert Definition } };
-
@pumuckl: Hmm naja ok wenn ich m_array(new T[m_size]) da stehen hätte, hättest du recht

-
camper schrieb:
Umgekehrt ist der Compiler aber nur dort verpflichtet, Ausdrücke beim Compilieren auszuwerten, wenn die Sprache an dieser Stelle einen konstanten Ausdruck erwartet.
Danke für die Erklärung.
Ich habe leider gerade mein Effective C++ nicht zur Hand, erinnere mich aber vage, dass es Meyers auf gleiche Weise falsch gemacht hat wie ich. Daher verzeihe ich mir selbst mal.
