2015-01-16 14 views
5

Ich habe einige Konstanten, die nur zur Kompilierzeit verwendet werden müssen, um den Code zu vereinfachen, also brauche ich die zur Laufzeit verfügbaren Variablen nicht.Wie definiert man während einer C++ Klasse eine konstante Konstante für die Kompilierung?

Traditionell wurde dies mit #define NAME 123 gemacht, aber ich möchte eine typsichere Alternative.

Außerhalb der Klassen können Sie const int name = 123;, die gut funktioniert, aber es scheint nicht möglich, dies innerhalb einer Klasse zu setzen. Zum Beispiel diese:

class Example { 
    public: 
     const double usPerSec = 1000000.0; 
}; 
double usOneMinute = 60 * Tempo::usPerSec; 

Arbeiten mit Visual C++, aber mit GCC funktioniert nicht:

error: non-static const member ‘const double Example::usPerSec’, 
    can’t use default assignment operator 

Sie können das Problem beheben, indem sie statisch zu machen, aber dann Visual C++ klagt:

error C2864: 'Example::usPerSec' : a static data member with an in-class 
    initializer must have non-volatile const integral type 
    type is 'const double' 

Ich vermute, das bedeutet VC++ akzeptiert nur static const int.

Ich möchte vermeiden, den Wert im Konstruktor zu setzen, weil ich dann eine Instanz der Klasse zur Laufzeit benötigt, um auf den Wert zuzugreifen, während ich eigentlich alles zur Kompilierzeit behandelt werden möchte wie mit #define.

Also wie kann ich eine Konstante als double innerhalb einer Klasse definieren, ohne es global zu machen oder #define verwenden, die ohne eine Instanz der Klasse funktioniert, und die mit großen C++ 03 Compiler funktioniert ?

Antwort

10

Es gibt einen Unterschied hier zwischen festen und anderen Typen.Für ganzzahlige Typen Sie sie als const static Mitglieder wie in

struct Example 
{ 
    const static int name = 123; // added 'static' to code in text of question 
    const static unsigned usPerSec = 1000000; 
}; 

für nicht-ganzzahligen Typen immer definieren können, wie double in Ihrem Beispiel ist die Situation komplizierter. Seit 2011 (Compiler-Option std=c++11 mit den meisten Compilern), können Sie einfach tun:

struct Example 
{ 
    constexpr static double usPerSec = 1000000.0; 
}; 

Aber mit gcc, diese

struct Example 
{ 
    const static double usPerSec = 1000000.0; 
}; 

sollte auch arbeiten in C++ 03 (es ist eine GNU-Erweiterung).

jedoch die Standard-Ansatz in C++ 03, die auch von der Standardbibliothek verwendet wird selbst (zum Beispiel in std::numeric_limits<>), ist eine static Memberfunktion

struct Example 
{ 
    static double usPerSec() { return 1000000.0; } 
}; 
+1

'+ 1' für die Erwähnung von' std :: numeric_limits <> ', das halte ich für einen nützlichen Punkt. – Angew

1

Dieser Code sowohl auf vc arbeitet ++ und gcc:

class Example { 
public: 
    static const double usPerSec ; 
}; 
const double Example::usPerSec=10000.0; 
double usOneMinute = 60 * Example::usPerSec; 
4

Ich sehe zwei mögliche Ansätze mit C++ 03:

  1. Verwenden Sie eine statische Memberfunktion und stützen sich auf inlining:

    class Example { 
        public: 
         static double usPerSec() { return 1000000.0; } 
    }; 
    double usOneMinute = 60 * Example::usPerSec(); 
    
  2. Verwenden Sie ein statisches Datenelement und treten Sie bei konstantem Falten zurück (der Wert, der die Konstante verwendet, wird comp ausgeschüttete zur Laufzeit):

    class Example { 
        public: 
         static const double usPerSec; 
    }; 
    double usOneMinute = 60 * Example::usPerSec; 
    
    // Somewhere in one .cpp 
    const double Example::usPerSec = 1000000.0; 
    
+0

Die zweite Option gibt unaufgelöste externe, wenn Sie es in einer Bibliothek verwenden und mit MSVC++ kompilieren. Das Symbol in einer DLL exportieren zu müssen ist definitiv zu viel für eine angebliche Kompilierzeitkonstante, die normalerweise außerhalb der Bibliothek nicht sichtbar wäre! – Malvineous

1

Sie haben es static const zu machen und es dann außerhalb des Unterrichts geben zu schätzen wissen. Mach es nicht im Konstruktor. Sie müssen keine make-Instanz machen

class Example { 
public: 
    static const double usPerSec; 

};

double Example::usPerSec = 1000000.0; 

Jetzt können Sie es überall nutzen, ohne Instanz der Klasse zu machen

double someVar = Example::usPerSec; 
2

Wenn ich Sie wäre, würde ich setzen es in einem Namensraum:

namespace MyExampleNamespace { 
    const double usPerSec = 1000000.0; 
} 
double usOneMinute = 60 * MyExampleNamespace::usPerSec;