W PHP i C # stałe można zainicjować tak, jak są zadeklarowane:
class Calendar3
{
const int value1 = 12;
const double value2 = 0.001;
}
Mam następującą deklarację C ++ funktora, który jest używany z inną klasą do porównania dwóch wektorów matematycznych:
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;
};
Ten kod skompilowany bez problemów z g ++. Teraz w trybie C ++ 0x (-std = c ++ 0x) kompilator g ++ wyświetla komunikat o błędzie:
błąd: „constexpr” jest potrzebne do inicjalizacji w klasie statycznego elementu członkowskiego danych „tolerancja” typu niecałkowitego
Wiem, że mogę zdefiniować i zainicjować tego static const
członka poza definicją klasy. Ponadto niestatyczny stały element członkowski danych można zainicjować na liście inicjatorów konstruktora.
Ale czy istnieje sposób na zainicjowanie stałej w deklaracji klasy, tak jak jest to możliwe w PHP lub C #?
Aktualizacja
Użyłem static
słowa kluczowego tylko dlatego, że można było zainicjować takie stałe w deklaracji klasy w g ++. Potrzebuję tylko sposobu na zainicjowanie stałej w deklaracji klasy, bez względu na to, czy została zadeklarowana jako, static
czy nie.
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.
To zły sposób decydowania, czy członek powinien być,static
czy nie. Nigdy nie pozwól, aby leksykalne lenistwo decydowało o semantyce twojego kodu.That's the wrong way to decide whether a member should be static or not.
Nie zgadzam się. Myślę, że to nie ma znaczenia dla stałych członków.static
element członkowski z informacjami specyficznymi dla instancji. To, że zdecydowałeś, że twoja stała jest właściwością typu, a nie konkretną instancją, jest powodem, dla którego to zrobiszstatic
, a nie dlatego, że spodobał ci się skrót pisania.struct myType { const std::time_t instantiated; myType() : instantiated(std::time(0)) {} };
Wszystko, co może być,const
powinno byćconst
; dotyczy to zarówno członków, jakstatic
i osób niebędącychstatic
członkami.Odpowiedzi:
W języku C ++ 11 elementy niebędące
static
danymi , składowe danych i elementystatic constexpr
członkowskiestatic const
danych typu integralnego lub wyliczeniowego mogą być inicjowane w deklaracji klasy. na przykładstruct X { int i=5; const float f=3.12f; static const int j=42; static constexpr float g=9.5f; };
W tym przypadku element
i
członkowski wszystkich wystąpień klasyX
jest inicjowany5
przez konstruktora generowanego przez kompilator, a elementf
członkowski jest inicjowany w3.12
. Elementstatic const
członkowski danychj
jest zainicjowany42
, a elementstatic constexpr
członkowski danychg
jest zainicjowany9.5
.Ponieważ
float
idouble
nie są typu integralnego ani wyliczeniowego, takie elementy członkowskie muszą byćconstexpr
lub niestatic
, aby inicjator w definicji klasy był dozwolony.Przed C ++ 11 tylko
static const
elementy członkowskie danych typu integralnego lub wyliczeniowego mogą mieć inicjatory w definicji klasy.źródło
char const n[3]{'a', 'b', 'c'};
.static const int
alestatic constexpr float
? co to znaczyfloat and double are not of integral or enumeration type
?Inicjowanie statycznych zmiennych składowych innych niż stałe typy int nie jest standardem C ++ przed C ++ 11. Kompilator gcc nie ostrzeże Cię o tym (i mimo wszystko wygeneruje przydatny kod), chyba że określisz
-pedantic
opcję. Następnie powinien pojawić się błąd podobny do: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]
Powodem tego jest to, że standard C ++ nie precyzuje, w jaki sposób powinny być implementowane zmiennoprzecinkowe i jest pozostawiony procesorowi. Aby obejść ten i inne ograniczenia,
constexpr
wprowadzono.źródło
Tak. Po prostu dodaj
constexpr
słowo kluczowe zgodnie z błędem.źródło
Jeśli potrzebujesz go tylko w jednej metodzie, możesz zadeklarować to lokalnie statycznie:
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 ); } };
źródło
Napotkałem z tym prawdziwe problemy, ponieważ potrzebuję tego samego kodu do kompilacji z różnymi wersjami g ++ (kompilator GNU C ++). Musiałem więc użyć makra, aby zobaczyć, która wersja kompilatora jest używana, a następnie postępować zgodnie z tym
#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;
Spowoduje to użycie „const” dla wszystkiego przed wersją g ++ 6.0.0, a następnie „constexpr” dla wersji g ++ 6.0.0 i nowszych. To przypuszczenie w wersji jeżeli zmiana ma miejsce, ponieważ szczerze mówiąc nie zauważyłem tego momentu g ++ w wersji 6.2.1. Aby zrobić to dobrze, być może będziesz musiał spojrzeć na wersję pomocniczą i numer poprawki g ++, więc zobacz
https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html
aby uzyskać szczegółowe informacje na temat dostępnych makr.
W przypadku gnu możesz również trzymać się wszędzie używania „const”, a następnie kompilować z
-fpermissive
flagą, ale to daje ostrzeżenia i lubię, aby moje rzeczy kompilowały się czysto.Niezbyt dobre, ponieważ jest specyficzne dla kompilatorów gnu, ale podejrzewam, że można by było zrobić coś podobnego z innymi kompilatorami.
źródło