In PHP und C # können die Konstanten so initialisiert werden, wie sie deklariert sind:
class Calendar3
{
const int value1 = 12;
const double value2 = 0.001;
}
Ich habe die folgende C ++ - Deklaration eines Funktors, der mit einer anderen Klasse verwendet wird, um zwei mathematische Vektoren zu vergleichen:
struct equal_vec
{
bool operator() (const Vector3D& a, const Vector3D& b) const
{
Vector3D dist = b - a;
return ( dist.length2() <= tolerance );
}
static const float tolerance = 0.001;
};
Dieser Code wurde ohne Probleme mit g ++ kompiliert. Im C ++ 0x-Modus (-std = c ++ 0x) gibt der g ++ - Compiler eine Fehlermeldung aus:
Fehler: 'constexpr' wird für die klasseninterne Initialisierung der 'Toleranz' des statischen Datenelements vom nicht integralen Typ benötigt
Ich weiß, dass ich dieses static const
Mitglied außerhalb der Klassendefinition definieren und initialisieren kann . Außerdem kann ein nicht statisches konstantes Datenelement in der Initialisierungsliste eines Konstruktors initialisiert werden.
Aber gibt es eine Möglichkeit, eine Konstante innerhalb der Klassendeklaration so zu initialisieren, wie es in PHP oder C # möglich ist?
Aktualisieren
Ich habe das static
Schlüsselwort verwendet, nur weil es möglich war, solche Konstanten innerhalb der Klassendeklaration in g ++ zu initialisieren. Ich brauche nur eine Möglichkeit, eine Konstante in einer Klassendeklaration zu initialisieren, egal ob sie als deklariert ist static
oder nicht.
I used static keyword just because it was possible to initialize such constants within the class declaration in g++. I just need a way to initialize a constant in a class declaration no matter if it declared as static or not.
Das ist der falsche Weg, um zu entscheiden, ob ein Mitglied sein sollstatic
oder nicht. Lassen Sie niemals die lexikalische Faulheit über die Semantik Ihres Codes entscheiden.That's the wrong way to decide whether a member should be static or not.
Ich stimme nicht zu. Ich denke, das ist für ständige Mitglieder nicht wichtig.static
konstantes Mitglied mit instanzspezifischen Informationen initialisieren . Dass Sie entschieden haben, dass Ihre Konstante eher eine Eigenschaft des Typs als einer bestimmten Instanz ist, ist der Grund dafür,static
und nicht, weil Sie sich eine Eingabeverknüpfung vorgestellt haben.struct myType { const std::time_t instantiated; myType() : instantiated(std::time(0)) {} };
Alles, was kann seinconst
sollte seinconst
;static
Dies gilt sowohl für Nichtmitglieder als auch fürstatic
Nichtmitglieder.Antworten:
In C ++ 11 können Nicht-
static
Datenelemente,static constexpr
Datenelemente undstatic const
Datenelemente vom Integral- oder Aufzählungstyp in der Klassendeklaration initialisiert werden. z.Bstruct X { int i=5; const float f=3.12f; static const int j=42; static constexpr float g=9.5f; };
In diesem Fall ist das
i
Mitglied aller Instanzen der KlasseX
initialisiert wird, um5
durch den Compiler generierten Konstruktor und dasf
Element wird initialisiert3.12
. Dasstatic const
Datenelementj
wird auf initialisiert42
und dasstatic constexpr
Datenelementg
wird auf initialisiert9.5
.Da
float
unddouble
nicht vom Integral- oder Aufzählungstyp sind, müssen solche Elemente entwederconstexpr
oder nicht seinstatic
, damit der Initialisierer in der Klassendefinition zulässig ist.Vor C ++ 11 konnten nur
static const
Datenelemente vom Integral- oder Aufzählungstyp Initialisierer in der Klassendefinition haben.quelle
char const n[3]{'a', 'b', 'c'};
.static const int
aberstatic constexpr float
? was bedeutet esfloat and double are not of integral or enumeration type
?Das Initialisieren anderer statischer Elementvariablen als const int-Typen ist vor C ++ 11 kein Standard-C ++. Der gcc-Compiler warnt Sie nicht davor (und erzeugt dennoch nützlichen Code), es sei denn, Sie geben die
-pedantic
Option an. Sie sollten dann einen Fehler erhalten, der ähnlich ist wie:const.cpp:3:36: error: floating-point literal cannot appear in a constant-expression const.cpp:3:36: warning: ISO C++ forbids initialization of member constant ‘tolerance’ of non-integral type ‘const float’ [-pedantic]
Der Grund dafür ist, dass der C ++ - Standard nicht spezifiziert, wie Gleitkomma implementiert werden soll, und dem Prozessor überlassen bleibt. Um diese und andere Einschränkungen zu umgehen,
constexpr
wurde eingeführt.quelle
Ja. Fügen Sie einfach das
constexpr
Schlüsselwort hinzu, wie der Fehler sagt.quelle
Wenn Sie es nur in einer Methode benötigen, können Sie es lokal statisch deklarieren:
struct equal_vec { bool operator() (const Vector3D& a, const Vector3D& b) const { static const float tolerance = 0.001f; Vector3D dist = b - a; return ( dist.length2() <= tolerance ); } };
quelle
Ich bin dabei auf echte Probleme gestoßen, weil ich denselben Code zum Kompilieren mit verschiedenen Versionen von g ++ (dem GNU C ++ - Compiler) benötige. Also musste ich ein Makro verwenden, um zu sehen, welche Version des Compilers verwendet wurde, und dann entsprechend handeln
#if __GNUC__ > 5 #define GNU_CONST_STATIC_FLOAT_DECLARATION constexpr #else #define GNU_CONST_STATIC_FLOAT_DECLARATION const #endif GNU_CONST_STATIC_FLOAT_DECLARATION static double yugeNum=5.0;
Dies verwendet 'const' für alles vor g ++ Version 6.0.0 und dann 'constexpr' für g ++ Version 6.0.0 und höher. Das ist eine Vermutung für die Version, in der die Änderung stattfindet, denn ehrlich gesagt habe ich dies erst in g ++ Version 6.2.1 bemerkt. Um es richtig zu machen, müssen Sie sich möglicherweise die Nebenversion und die Patch-Nummer von g ++ ansehen
https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html
Einzelheiten zu den verfügbaren Makros.
Mit gnu könnten Sie auch überall bei der Verwendung von 'const' bleiben und dann mit dem
-fpermissive
Flag kompilieren , aber das gibt Warnungen aus und ich möchte, dass meine Sachen sauber kompiliert werden.Nicht großartig, weil es spezifisch für Gnu-Compiler ist, aber ich vermute, Sie könnten es mit anderen Compilern ähnlich machen.
quelle