anfängerfrage: #define oder const ?



  • Hallo,

    ich will eine konstante definieren die eigentlich nur in meiner klasse genutzt wird in mehreren methoden. Jetzt weiß ich nicht was die gewöhnliche c++ art ist...
    ist es besser
    #define C 7

    oder
    private:
    const int c = 7;

    zu schreiben???

    Ich danke euch für Hilfe...



  • const int ist in allen punkten vorzuziehen.
    define wurde für sowas in c bisbraucht.



  • danke,

    wie soll ich denn aber im header dann const definieren? weil
    im header kann ich ja keine zuweisung machen....

    ...
    const double c = 7;
    ...
    

    ich kann dann ja nur

    ...
    double c;
    ...
    

    und dann c einen wert zuweisen

    Oder wo steh ich auf dem schlauch
    😕



  • da du vorhattest mit define zu arbeiten schätze ich einfach mal das du eigentlich mehrere konstannten hattest die dann den Zustand von was auch immer in deiner klasse beschreiben richtig?
    In dem Fall könntest du auch enum verwenden.

    Und nebenbei.

    In der Klassendeklaration kannst du keine Zuweisungen machen wie sie in deinem const-beispiel stattfinden.

    Willst du ein konstantes Ellement in deiner KLasse musst du ihr einen Wert durch den Konstruktor zuweisen zwischen Bezeichner und Rumpf, auf keinen Fall im Rumpf selbst, dort ist es ein Fehler.

    EDIT:
    Wieso sollte man im Header keinen Wert zuweisen können?

    EDIT2:

    für eine constvariable die NICHT in der Klasse ist aber dennoch im Header benutze lieber enum.
    Dieses Zeug kann man nämlihc auch in mehrere cpp-Dateien einfügen ohne Fehler wegen Mehrfachdeklaration zu bekommen.



  • Das Beispiel war aber ein double ...



  • Also wenn du es nicht als Attribut in einer Klasse hast, mußt du extern benutzen.

    Im Header:

    extern const double c;
    

    Und in der CPP:

    const double c = 7;
    


  • danke kahino!

    was ich möchte ist eine konstante die nur in der klasse verwendet wird (in mehreren methoden) die aber nie ihren wert ändern darf/wird.

    ich bin etwas verwirrt was das const jetzt angeht...ich kann doch nicht in der klassendeklaration sagen:

    const double c;

    und dann im header:
    c = 7;

    aber wenn ich c in der klassendeklaration verwenden will muss ich ja zwangsläufig schreiben:

    double c;

    und den wert dann zuweisen im konstruktor - habe dann aber kein const element mehr ???

    ich habe mich wohl falsch ausgedrückt...wie du schon sagtest kann man anscheinend in einer klassendeklaration keinen wert zuweisen - sondern dann wohl halt im header aber halt ausserhalb der klassendeklaration z.B in einem enum...wie du vorschlägst

    in meinem fall sollte ich dann wohl wie vorgehen - sorry für mein durcheinandersein...

    danke



  • Ist die Konstante für alle Instanzen der Klasse gleich? Dann musst du ein static const benutzen:

    // Header
    
    class A
    {
    public:
        static const int answer;
    };
    
    // eine beliebige Quellcodedatei
    const int A::answer = 42;
    

    (für integrale Typen kannst du auch die Zuweisung in der Deklaration machen, die Definition im Code ist trotzdem nötig)

    Wenn die Konstante für alle Instanzen unterschiedlich ist (z.B. per Konstruktor übergeben wird), dann musst du sie in der Konstruktorliste initialisieren:

    class A
    {
    public:
        A (int p) : _my_answer (p)
        {}
    private:
        const int _my_answer;
    };
    

    enums sind nur für Konstanten integraler Datentypen ein Ersatz, double/float und alle benutzerdefinierten Typen können damit nicht ausgedrückt werden.
    Für globale Konstanten benutzt du das Konstrukt, das Artchi beschrieben hat.

    Klar?

    /edit Hähä, akari, gotcha zum Zweiten 😉



  • Hallo

    dafür hast du dann die Initialisierungsliste des Konstruktors

    class MyClass
    {
      public :
        const int value;
        MyClass();
    };
    
    MyClass::MyClass() : value(2) // hier können (konstante) Werte initialisiert werden
    {
    }
    

    Diese Initialisierungliste sollte nicht nur für konstante Werte benutzt werden, sondern für alle anderen auch.
    bei statischen Membervariablen sieht das natürlich schon wieder anders aus.

    bis bald
    akari



  • aha...vielen dank an euch! Jetzt versteh ich auch was diese initialisierungslisten darstellen 🙂

    Danke an eure große Hilfe!

    EDIT:
    die initialisierungsliste sollte für alle werte genutzt werden? habe ich das richtig verstanden? Also alles auch wenn ich ganz simpel:

    int a;

    und im konstruktor dann:

    a = 9;

    verwende?

    was bringt denn das? Laut dem Link mehr speed aber wenn der konstruktor eh ausgeführt werden muss??



  • Bei einfachen Typen kann es sein, dass es wegoptimiert wird, aber der normale Lauf der Dinge wäre, dass zu erst der Standardkonstruktor aufgerufen wird und dann die Zuweisung gemacht wird. Schreibst du direkt in die Initialisierungsliste, dann wird auch direkt der entsprechende Konstruktor aufgerufen.



  • @.filmor
    [quote]Das Beispiel war aber ein double ...[quote]
    Sein erstes Beispiel war ein int und die zuweisung folgte direkt nach "private:", was vorraussetzt in der Klassendeklaration zu sein o0

    @Matti

    ich kann doch nicht in der klassendeklaration sagen: ...

    Deswegen meinte ich ja zwischen Bezeichner und Rumpf des KOnstruktors, was akari auch betreffender als Initialisierungsliste bezeichnet hat.

    @.filmore

    Bei einfachen Typen kann es sein, dass es wegoptimiert wird, aber der normale Lauf der Dinge wäre, dass zu erst der Standardkonstruktor aufgerufen wird und dann die Zuweisung gemacht wird. Schreibst du direkt in die Initialisierungsliste, dann wird auch direkt der entsprechende Konstruktor aufgerufen.

    Die initialisierungslisten der verschiedenen Konstruktoren beeinflussen nicht die Wahl des Konstruktors.



  • Kahino schrieb:

    Sein erstes Beispiel war ein int und die zuweisung folgte direkt nach "private:", was vorraussetzt in der Klassendeklaration zu sein o0

    Ich meinte das Beispiel, das direkt vor deinem Post kam.

    Kahino schrieb:

    Die initialisierungslisten der verschiedenen Konstruktoren beeinflussen nicht die Wahl des Konstruktors.

    Wohl. Sie beinflussen die Wahl des Konstruktors des zu initialisierenden Elements. Normalerweise ist das der Standardkonstruktor, wird das Element aber in der Initialisierungsliste initialisiert, dann wird der entsprechende Konstruktor ausgewählt.



  • sry.
    Ich habe einfach nicht verstanden, dass du von den Konstruktoren der Objekte redest, die in der Initialisierungsliste stehen und nicht von dem Konstruktor des Objekts selbst, welches die Objekte enthält über deren Konstruktoren du sprichst o0.



  • .filmor schrieb:

    ...die Definition im Code ist trotzdem nötig...

    Ich hatte im Ohr, dass das bei "static member constants" nicht unbedingt notwendig ist, sondern nur, wenn man sie als "adressierbares Objekt" nutzen will.
    Habe ich das falsch in Erinnerung ?

    Gruß,

    Simon2.



  • .filmor schrieb:
    ...die Definition im Code ist trotzdem nötig...

    Ich hatte im Ohr, dass das bei "static member constants" nicht unbedingt notwendig ist, sondern nur, wenn man sie als "adressierbares Objekt" nutzen will.
    Habe ich das falsch in Erinnerung ?

    Gruß,

    Simon2.

    Nein, deine Ausage ist korrekt!

    Laut neuestem Standard (den nun auch der MSVC seit Version 7.1 unterstützt), sind diese beiden Deklarationen äquivalent:

    class X
    {
       static const int X1 = 42;
       enum { X2 = 42 };
    };
    

    Und die Definition von X1 kann entfallen, solange man nur den Wert (und nicht die Adresse) benutzt.



  • Na,

    da bin ich ja beruhigt. 😉
    Allerdings:

    Th schrieb:

    ...

    class X
    {
       static const int X1 = 42;
       enum { X2 = 42 };
    };
    

    ..

    ... bei der "static const member"-Variante kann ich doch auch andere Typen nehmen als bei enums, oder ?
    (ich frage wegen des Wortes "äquivalent")

    Gruß,

    Simon2.


Anmelden zum Antworten