wie und wo konstante Werte definieren



  • Hallo,
    bin recht neu mit C++ und hab eine Frage wie man am besten, schönsten etc. konstante Werte definiert.

    Schon mehrmals hab ich gelesen #define sei in C++ verpönt. Ok, dann verwende ich statt #define DEFAULT_VAL 30 eben const int DEFAULT_VAL = 30;

    Da mein Projekt aber größer ist und ich mehrere konstante Werte (evtl. mit gleichem Namen) habe wäre es schön wenn ich die Konstanten über den Klassennamen ansprechen könnte z.B.

    class myClass
    {
    public:
        static const int    DEFAULT_VAL = 30;
        ...
    }
    
    int main(){
        int myVal = myClass::DEFAULT_VAL;
    }
    

    Funktioniert soweit auch ganz gut. Das Problem taucht dann nur auf, wenn ich Strings mit einem #define ersetzen möchte. Dann muss ich ja das
    static const char DEFAULT_STR[];
    in der Klassendefinition anlegen aber im Konstruktor dann nochmal initialisieren:

    myClass:myClass(){
        DEFAULT_STR[] = "kein Wert";
    }
    

    Wenn ich die String Konstante außerhalb der Klasse anlege, kann ich sie direkt initialisieren. Super. Allerdings ist der Name dann überall dort gültig bzw. bekannt, wo ich die Headerdatei einbinde und ich muss wieder ellenlange Namen für die Konstanten verwenden, damit nicht manche doppelt vorkommen.

    Ich würde gerne wissen, wie Ihr dabei vorgeht oder wie ich sowas am C++-konformsten in den Griff kriege.
    Hab mir überlegt, wenn ich die Konstanten im Header außerhalb der Klasse in einen Namespace packe, der den änlichen Namen wie die Klasse hat. Wäre ne Art workaround aber lässt sich das nicht noch besser realisieren..?

    namespace myClassConst{
        const char DEFAULT_STR[] = "kein Wert";
    }
    
    int main(){
        char myStr[] = myClassConst::DEFAULT_STR;
    }
    


  • Du musst beachten, dass all das, was Du innerhalb einer Klassendefinition mit der Form

    static [const] Typ Name ...
    

    schreibst, nur eine Deklaration ist. Eine Sonderregel erlaubt Dir die Angabe eines Initislisierers für Ganzzahlkonstanten, aber nicht mehr. Es ist dann aber immernoch keine Definition.

    Auf Namensraumebene ist ein

    const Typ Name = soundso;
    

    für viele Typen unproblematisch. Beachte, dass das const auf oberster Ebene dazu führt, dass Name eine interne Bindung bekommt. Es gibt also in jeder Übersetzungseinheit, in der Du die Headerdatei einbindest, ein eigenes Objekt Name. Bei "primitiven" Konstanten ist das kein Problem. Sofern Du Dir nicht die Adresse einer solchen Konstante holst oder sie an eine Referenz bindest, wird der Compiler das Ding einfach wegoptimieren und ähnlich wie bei #define im Rest des Programms eine einfache aber typsichere Ersetzung durchführen. Bei Arrays oder Stringkonstanten kann man das theoretisch auch so machen, sollte man aber vielleicht vermeiden. Eine String-Konstante unbekannter Länge kann man zB so deklarieren:

    //header
      #ifndef MEINE_KONSTANTEN_INCLUDED
      #define MEINE_KONSTANTEN_INCLUDED
    
      namespace constants {
    
      const int foo = 24;
      const double pi = 3.14159265;
    
      extern const char greetings[]; // unvollständiger Typ
    
      }
    
      #endif
    
    //cpp
      #include "constants.hpp"
    
      namespace constants {
    
      extern const char greetings[] = "Hello World!";
    
      }
    

    Oder mit einer Klasse:

    // header
    class Foo
    {
    public:
      static const char dings[]; // deklaration
    };
    
    // cpp
    #include "header"
    
    const char Foo::dings[] = "blah";
    

    In beiden Fällen muss das CPP kompiliert und mit dem Rest gelinkt werden.


  • Mod

    Beachte außerdem: const char* ist ein Zeiger auf ein Array von konstanten chars. Was du willst ist ein konstanter Zeiger auf ein Array von konstanten chars: const char* const


Anmelden zum Antworten