defines in c++: alternative möglichkeit?
-
Je nach dem was
_Tist, wird die Variante von unskilled nicht funktionieren.Normalerweise (gettext) belässt man für Übersetzungen die Zeichenkette und verwendet dann im Code
_("language")bzw. bei dir _T(...).
Das würde das Headerfile überflüssig machen.Für globale Instanzen (Singletons) kann man auch Funktionen schreiben, die den Wert zurückgeben, bei den Äquivalenten von den "ziemlich vielen defines" macht das wenig Sinn.
-
Je nach dem was _T ist, wird die Variante von unskilled nicht funktionieren.
weil?
das ich TCHAR und nicht char verwendet habe ist dir aber aufgefallen? oder hauptsache einfach mal posten und danach erst nachdenken?
-
gettext schrieb:
völligen Unsinn
Unskilled hat es doch gezeigt, wie je nach Einstellung MBCS oder UNICODE verwendet werden kann.
Edit: Ich hatte MBCS bzw. UNICODE geschrieben
-
Ich finde "Stringkonstanten" als
#defines eigentlich gar nicht soooo schlecht. Die Zeichenketten lassen sich so zumindest zur Compile-Zeit zusammensetzen. Beispiel:#define DINGS "bums" int main() { std::cout << "Blah " DINGS " blah blah!\n"; }Und sonst gefällt mir noch dieser Ansatz:
constants.hpp:#ifndef CONSTANTS_HPP_INCLUDE_GUARD #define CONSTANTS_HPP_INCLUDE_GUARD namespace constants { extern const char dings[]; // externe Bindung const char * const bums = "bar"; // interne Bindung, da const const double pi = 3.14159265; // interne Bindung, da const } #endifconstants.cpp:
#include "constants.hpp" namespace constants { extern const char dings[] = "foo"; }
-
krümelkacker schrieb:
Ich finde "Stringkonstanten" als
#defines eigentlich gar nicht soooo schlecht. Die Zeichenketten lassen sich so zumindest zur Compile-Zeit zusammensetzen. Beispiel:#define DINGS "bums" int main() { std::cout << "Blah " DINGS " blah blah!\n"; }Und sonst gefällt mir noch dieser Ansatz:
constants.hpp:#ifndef CONSTANTS_HPP_INCLUDE_GUARD #define CONSTANTS_HPP_INCLUDE_GUARD namespace constants { extern const char dings[]; // externe Bindung const char * const bums = "bar"; // interne Bindung, da const const double pi = 3.14159265; // interne Bindung, da const } #endifconstants.cpp:
#include "constants.hpp" namespace constants { extern const char dings[] = "foo"; }naja - und string-konstanten haben jz welchen nachteil? oO
bb
-
unskilled schrieb:
naja - und string-konstanten haben jz welchen nachteil? oO
Das sagte krümelkacker doch?
→ Gegenüber#define: Dass man sie nicht konkatenieren kann.
→ Gegenüberextern-Strings: Dass sie interne Bindung haben.Allerdings sehe ich nicht gerade, wieso krümelkacker stattdessen ein Array nimmt. Man könnte man ja auch
// Header extern const char* string; // Implementierungsdatei const char* string = "Hallo";benutzen.
-
"..konkatenieren.."
wie oft nutzt du das?
ich nie..."Gegenüber extern-Strings: Dass sie interne Bindung haben"
natürlich kann man auch noch - je nach wahl - extern oder static nutzen
bb
-
unskilled schrieb:
"..konkatenieren.."
wie oft nutzt du das?Ich habe es nur erwähnt, weil ich das kürzlich so genutzt habe.
unskilled schrieb:
natürlich kann man auch noch - je nach wahl - extern oder static nutzen

...wobei ich aber von so etwas
const char bums[] = "blah";in einem Header absehen würde, weil jede Übersetzungsinheit, die diesen Header einbindet, ihr eigenes Array bekommen würde. In der Hoffnung, dass der Linker Stringkonstanten vereinen kann, hatte ich oben
const char * const bums = "blah";geschrieben. Ich habe das aber bisher nie überprüft und deswegen hole ich das jetzt nach...
Test:
constants.hpp (definiert konstante als zeiger ODER array mit interner bindung)
main.cpp (enthält main, gibt konstante auf cout aus und ruft greet auf)
greet.cpp (enthält greet, gibt konstante auf cout aus)Compiler/Linker: GCC/ld
Ergebnis: In beiden Varianten taucht die Stringkonstante doppelt in der ausführbaren Datei auf. Um das zu vermeiden, kann man es so machen, wie ich es oben bei constants::dings gezeigt habe.
-
Und wenn man sie static macht? Bleibt das Problem der doppelten Stringkonstanten dann noch immer bestehen?
-
oh - hätte ich nicht gedacht, dass der linker das nciht kann... -.-
vll kanns ja der msvc - aber lust das auszuprobieren hab ich iwie nicht : Dlösung, die definitiv immer klappt wäre halt, es nur zu deklarieren und im source zu definieren.
mit static könnte man es auch noch versuchen, aber ich glaube nicht, dass dem linker dadurch dann auf einmal die erleuchtung kommen wird
bb
-
krümelkacker schrieb:
Um das zu vermeiden, kann man es so machen, wie ich es oben bei constants::dings gezeigt habe.
Wieso ein Array und kein Zeiger mit externer Bindung? Die Definition mit der Initialisierung des Literals steht dann erst in der .cpp-Datei.
nnnnnnnnnnn schrieb:
Und wenn man sie static macht? Bleibt das Problem der doppelten Stringkonstanten dann noch immer bestehen?
Natürlich, mit
staticsagt man ja explizit, dass interne Bindung erwünscht ist.
-
Nexus schrieb:
krümelkacker schrieb:
Um das zu vermeiden, kann man es so machen, wie ich es oben bei constants::dings gezeigt habe.
Wieso ein Array und kein Zeiger mit externer Bindung?
Willkür.
Nexus schrieb:
nnnnnnnnnnn schrieb:
Und wenn man sie static macht? Bleibt das Problem der doppelten Stringkonstanten dann noch immer bestehen?
Natürlich, mit
staticsagt man ja explizit, dass interne Bindung erwünscht ist.Mit anderen Worten: Ob ich auf Namensraum-Ebene
static const int foo = 23;oder
const int foo = 23;schreibe, macht keinen Unterschied, da C++ für konstante Objekt schon automatisch eine interne Bindung verwendet. Lässt man das const weg, macht es einen Unterschied, weil sonst externe Bindung für nicht-konstante Objekt automatisch verwendet wird. Daher habe ich abundzu auch extern verwendet, um externe Bindung bei const-Objekten zu erzwingen.
Ich habe gerade im C++ Standard folgendes entdeckt:
7.1.2/4 schrieb:
...A string literal in the body of an extern inline function is the same object in different translation units...
Diesen Fall hatte ich eigentlich auch getestet, aber die Zeichenkette ist trotzdem mehr als einmal in der ausführbaren Datei gelandet.

#ifndef KONSTANTEN #define KONSTANTEN inline char const* foo() { return "superkalifragilistigexpialigetisch"; } #endifEs taucht doppel im Executable auf, aber die Adresse, die immer zurückgegeben wird, ist trotzdem die gleiche. Komisch. Scheint eine der zwei Stringkonstanten überflüssig zu sein.
Edit: Habe die letzten Tests nochmal mit clang++ statt g++ wiederholt. Und siehe da, ich finde keine doppelten Zeichenketten mehr im Exeucutable -- nicht mal mehr in dem Fall, wo ich eigentlich gedacht hatte, dass es zweimal auftauchen müsste.
