[Howto] Initialisierung konstanter, statischer Member-Vektoren
-
Moin,
folgendes Problem: Ich habe eine Klasse, welche einen (konstanten,) statischen Vektor von Strings enthält. Dieser Vektor muss nun initialisiert werden. Zur Zeit mache ich das in etwa so:
// scanner.hpp class Scanner { static std::vector<std::wstring> keywords; static bool isInitialized; }; // scanner.cpp bool Scanner::isInitialized = false; vector<wstring> Scanner::keywords; Scanner::Scanner(void) { if(!isInitialized) { isInitialized = true; keywords.push_back(L"Abstract"); keywords.push_back(L"Case"); // ... } }Diese Methode hat zwei Nachteile: Der Code zur Initialisierung ist ganz schön lang (und daher in eine andere Datei ausgelagert) und 'keywords' ist nicht 'const'.
Meine Frage: Wäre es besser, 'keywords' als 'const' zu deklarieren und mithilfe eines C-Style-Arrays zu initialisieren?
Das sähe denn in etwa so aus:
class Scanner { static const std::wstring _keywords[] = { L"Abstract", L"Case", /* ... */ }; static const int _num_keywords = 50; static const std::vector<std::wstring> keywords(&_keywords[0], &_keywords[_num_keywords]); }Hierbei erstellt man aber redundant Daten.
Was ist der bessere Stil? Gibt es noch eine (bessere) Methode, die ich übersehen habe?
-
Du würdest über den Satz "only static const integral data can be initialized inside of a class or struct" stolpern, der mir schon manches mal die Freude verdorben hat.
Die Lösung ist, innerhalb der Klasse das Datenelement nur zu deklarieren und es in einer Übersetzungsheit (.cpp) dann einmalig zu definieren.
-
Optimizer schrieb:
Du würdest über den Satz "only static const integral data can be initialized inside of a class or struct" stolpern, der mir schon manches mal die Freude verdorben hat.
Die Lösung ist, innerhalb der Klasse das Datenelement nur zu deklarieren und es in einer Übersetzungsheit (.cpp) dann einmalig zu definieren.Ok, das meinte ich. Dann sähe der alternative Code eben so aus:
// scanner.hpp class Scanner { static const std::wstring _keywords[]; static const int _num_keywords = 50; static const std::vector<std::wstring>; } // scanner.cpp const wstring Scanner::_keywords[] = { L"Abstract", L"Case", /* ... */ }; const vector<wstring> Scanner::keywords(&_keywords[0], &_keywords[_num_keywords]);Das funktioniert. Aber ist es besserer Stil als die andere Methode?
-
Mit Sicherheit, bei deiner Methode initialisierst du etwas statisches, also nicht Instanz-gebundenes erst, wenn du eine Instanz erstellst. Das ist IMHO ziemlich ugly und auch nicht der Sinn von statischen Membern einer Klasse. C++ kennt leider keine statischen Konstruktoren, also denke ich, ist das das beste was du machen kannst.
-
Ok, ich danke recht herzlich für die Antwort und werde meinen Code entsprechend anpassen.
-
// scanner.hpp class Scanner { static const std::vector<std::wstring> keywords; }; // scanner.cpp namespace { vector<wstring> initKeywords() { vector<wstring> res; res.push_back(L"Abstract"); res.push_back(L"Case"); // ... return res; } } const vector<wstring> Scanner::keywords = initKeywords();Die Funktion kannst du ja zur Not irgendwo Richtung Dateiende implementieren oder ganz auslagern...