Ein weiterer Versuch:
Dies wird jämmerlich fehlschlagen, da const_val intern einen char * m_val beinhaltet. Die Initialisierung von USER_NAME aus einem Properties-Objekt kopiert einen nullterminierten String zu m_val. m_val ist jedoch NULL und eine Zugriffsverletzung trifft ein. m_val muss Speicher zugewiesen werden, der bei der Destruktion von const_val gelöscht werden sollte.
Eine Methode besteht darin, intern std::string beizubehalten und nach außen hin eine const char*-Umwandlung zu bieten. Genau das wird auch getan: Bei rohen char* Strings behält man intern std::strings bei. Hier erfordert die Lösung Traits, die den Klassen entsprechend erweitert werden können.
In den vorhergehenden Lösungen sorgten dependent_statics dafür, dass die Initialisierung statischer Variablen aufgeschoben wurde. Die Variable dependent_statics wird automatisch beim Aufruf von constants_and_dependents::initialize() initialisiert. Eine dependent_static muss jedoch nicht global sein. Der in Listing L gezeigte Code wird fehlschlagen.
Dagegen können const_val Konstanten nur global sein. Soll eine konstante Variable nur für eine Funktion gelten, ist const_val nicht erforderlich. Die Initialisierung einer lokalen Variable sollte nicht aufgeschoben, sondern umgehend stattfinden, und zwar mit get_prop_val:
Das war’s denn schon. Die endgültige Lösung ist in Listing M zu finden.
Weiterführende Themen
Wandelt man eine globale/statische Variable in dependent_static< type> um, hat man normalerweise keine Probleme. Es gibt jedoch ein paar Situationen, in denen der Übergang nicht gar so unkompliziert ist:
- Bei der Übergabe einer Referenz an ein Objekt
- Bei der Übergabe eines Objekts, dessen Klasse keinen Kopierkonstruktur hat
- Bei der Übergabe von const_val oder einer anderen dependent_static
Der Grund hierfür ist, dass dependent_static alle Parameter als Wert übernimmt. Will man eine Referenz übergeben, sollte eine Referenzklasse wie boost::ref/cref verwendet werden.
Wenn man ein Objekt übergeben will, dessen Klasse keinen Kopierkonstruktor hat, tritt ein Kompilierzeitfehler auf. Deshalb sollte das Objekt als Referenz übergeben werden. Möchte man eine const_val oder eine andere dependent_static übergeben, sollte man daran denken, dass diese nicht kopiert werden können, weswegen sie als Referenz übergeben werden müssen. Listing N zeigt Beispiele jeder Referenzübergabe.
Fazit
Der Wechsel zwischen Kompilierzeit- und Laufzeit-Konstanten sollte eigentlich einfach sein, ist es aber bei weitem nicht. Aus diesem Grund wurde hier die Kombination const_val und dependent_static entwickelt, was die Sache wesentlich einfacher macht. Noch ein letzter Hinweis: Laufzeit-Konstanten sollten immer zuerst Defaultwerte vergeben werden. Anschließend sind so viele Konstanten wie nur möglich von Kompilierzeit- in Laufzeit-Konstanten umzuwandeln. Auf diese Weise erhält man mehrere Sets von Konstanten, die zur Laufzeit zur Auswahl stehen, wodurch das Austesten/Debuggen/Profiling der Anwendung vereinfacht wird.
Neueste Kommentare
Noch keine Kommentare zu Umwandlung von Kompilierzeit-Konstanten zu Laufzeit-Konstanten und umgekehrt
Kommentar hinzufügenVielen Dank für Ihren Kommentar.
Ihr Kommentar wurde gespeichert und wartet auf Moderation.