Statinė pastovi eilutė (klasės narys)

Norėčiau turėti asmeninę statinę pastovią klasę (šiuo atveju - formos gamyklą).

Norėčiau kažką daryti.

 class A { private: static const string RECTANGLE = "rectangle"; } 

Deja, gaunu visų rūšių klaidas iš C ++ kompiliatoriaus (g ++), pavyzdžiui:

ISO C ++ draudžia elemento RECTANGLE inicijavimą

negaliojančio klasės inicijavimas statinio nario, kuris nėra nuolatinis tipas „std :: string

klaida: „STANDARD STATION RECTANGLE“ sukūrimas

Tai rodo, kad toks nario dizainas neatitinka standarto. Kadangi jūs turite asmeninį pažodinį (arba galbūt viešai prieinamą), nenaudodami #define direktyvos (noriu išvengti pasaulinio duomenų vientisumo!)

Bet kokia pagalba yra vertinama.

385
nustatyti lb. Spalio 14 d 2009-10-14 05:00 '09 5:00 val. 2009-10-14 05:00
@ 11 atsakymų

Turite apibrėžti savo statinį narį už klasės apibrėžties ir pateikti iniciatorių.

Pirma

 // In a header file (if it is in a header file in your case) class A { private: static const string RECTANGLE; }; 

ir tada

 // In one of the implementation files const string A::RECTANGLE = "rectangle"; 

Sintaksė, kurią iš pradžių bandėte naudoti (klasės iniciatoriaus apibrėžimas) leidžiama tik su integruotais ir išvardytais tipais.

409
14 окт. atsakymas duotas AnT spalio 14 d. 2009-10-14 05:03 '09, 5:03 2009-10-14 05:03

C ++ 11 galite tai padaryti dabar:

 class A { private: static constexpr const char* STRING = "some useful string constant"; }; 
139
21 июня '14 в 14:27 2014-06-21 14:27 atsakymas įdėtas į bedugnę.7 Birželio 21 d. 14, 27 val. 2014-06-21 14:27

Klasės apibrėžtyje galite deklaruoti tik statinius narius. Jie turi būti apibrėžti už klasės ribų. Dėl integruotų kompiliavimo laiko konstantų standartas išimtis, kurią galite „inicijuoti“. Tačiau tai dar nėra apibrėžimas. Pavyzdžiui, adresas neveiks be apibrėžimo.

Norėčiau paminėti, kad nematau naudos naudojant std :: string per const char [] konstantas. std :: string yra gera, ir viskas, išskyrus ją, reikalauja dinaminio inicijavimo. Taigi, jei rašote kažką panašaus

 const std::string foo = "hello"; 

vardų srityje konstruktoriaus foo bus paleistas prieš pat pagrindinius paleidimus, ir šis konstruktorius sukurs pastovios „hello“ kopijos krūvos atmintyje. Jei tikrai nereikia RECTANGLE būti std :: string, galite tiesiog parašyti

 // class definition with incomplete static member could be in a header file class A { static const char RECTANGLE[]; }; // this needs to be placed in a single translation unit only const char A::RECTANGLE[] = "rectangle"; 

Ten! Netinkamo krūvos atranka, kopijavimo trūkumas, dinamiško inicijavimo nebuvimas.

Sveikinimai, c.

30
14 окт. atsakymas pateikiamas sellibitze spalis 14. 2009-10-14 11:30 '09 11:30 val. 2009-10-14 11:30

Tai tik papildoma informacija, bet, jei jums tikrai reikia eilutės antraštės faile, pabandykite kažką panašaus:

 class foo { public: static const std::string RECTANGLE(void) { static const std::string str = "rectangle"; return str; } }; 

Nors abejoju, tai rekomenduojama.

15
14 окт. atsakymas, kurį pateikė GManNickG 14 okt. 2009-10-14 05:08 '09, 5:08 am. 2009-10-14 05:08

C ++ 17 galite naudoti įterptus kintamuosius:

 class A { private: static inline const std::string my_string = "some useful string constant"; }; 

Atkreipkite dėmesį, kad tai skiriasi nuo atsakymo į abyss.7 : tai apibrėžia faktinį std::string objektą, o ne const char*

8
02 марта '18 в 18:15 2018-03-02 18:15 Oz Saliamono atsakymas kovo 2 d. 18, 18:15 2018-03-02 18:15

Norėdami naudoti šią iniciaciją klasės sintaksėje, konstantas turi būti statinis const integralinis arba išvardytas tipas, inicijuotas pastovia išraiška.

Tai yra apribojimas. Todėl šiuo atveju reikia nustatyti kintamąjį už klasės ribų. nuoroda į @AndreyT pranešimą

7
atsakymą pateikė aJ. Spalio 14 d 2009-10-14 05:07 '09, 5:07 am. 2009-10-14 05:07

Dabartinis standartas leidžia tokį inicijavimą statiniams pastoviems integriniams tipams. Todėl jums reikia padaryti, kaip paaiškino AndreyT. Tačiau tai bus pasiekiama sekančiame standarte naudojant naują nario iniciacijos sintaksę .

4
14 окт. atsakymą pateikė Leandro TC Melo 14 okt. 2009-10-14 05:11 '09, 5:11 val. 2009-10-14 05:11

gal tiesiog:

 static const std::string RECTANGLE() const { return "rectangle"; } 

arba

 #define RECTANGLE "rectangle" 
4
27 марта '12 в 4:08 2012-03-27 04:08 atsakymas duotas chikubai kovo 27 d. 12 d. 4:08 2012-03-27 04:08

Galite eiti išspręsti aukščiau minėtą const char* , bet tada, jei jums reikia visą eilutę, turėsite daug pridėtinių.
Kita vertus, statinei eilutei reikalingas dinaminis inicializavimas, todėl, jei norite naudoti jo vertę kito globalinio / statinio kintamojo inicializavimo metu, galite susidurti su inicijavimo tvarkos problema. Norėdami to išvengti, pigiausias yra prieiga prie statinio eilutės objekto per „getter“, kuris patikrina, ar jūsų objektas yra inicijuotas, ar ne.

 //in a header class A{ static string s; public: static string getS(); }; //in implementation string A::s; namespace{ bool init_A_s(){ A::s = string("foo"); return true; } bool A_s_initialized = init_A_s(); } string A::getS(){ if (!A_s_initialized) A_s_initialized = init_A_s(); return s; } 

Nepamirškite naudoti A::getS() . Kadangi bet kuris pokalbis gali pradėti tik su main() , o A_s_initialized inicijuojamas į main() , jums nereikia užrakinti, net ir daugialypėje aplinkoje. A_s_initialized pagal nutylėjimą yra 0 (prieš dinamišką inicijavimą), taigi, jei prieš inicijavimą naudosite getS() , skambinate „init“ funkcijai saugiai.

Btw į pirmiau pateiktą atsakymą: "statinis const std :: string RECTANGLE () const", statinės funkcijos negali būti const , nes jos negali pakeisti būsenos, jei bet koks objektas bet kuriuo atveju yra (šis rodiklis nėra).

3
23 сент. atsakymas, kurį pateikė user2806882 Sep 23 2013-09-23 14:13 '13, 13:13 PM 2013-09-23 14:13

Statiniai klasės kintamieji gali būti deklaruojami antraštėje, tačiau jie turi būti apibrėžti .cpp faile. Taip yra dėl to, kad gali būti tik vienas statinio kintamojo egzempliorius, ir kompiliatorius negali nuspręsti, kuriame generuojamame objekto faile, kad galėtumėte priimti sprendimą.

Statinės vertės apibrėžimo išsaugojimas naudojant deklaraciją C ++ 11 gali naudoti įdėtą statinę struktūrą. Tokiu atveju statinis narys yra struktūra ir turi būti apibrėžtas .cpp faile, tačiau reikšmės yra antraštėje.

3
24 февр. Marko Mahnič atsakymas 24 vasaris 2017-02-24 10:54 '17 - 10:54 2017-02-24 10:54

Paspartinti iki 2018 m. Ir C ++ 17.

- nenaudokite std :: string, naudokite std :: string_view literatūrą - atkreipkite dėmesį į žemiau esantį „constexpr“. Tai taip pat yra „kompiliavimo laiko“ mechanizmas. - ne eilutė nereiškia pasikartojimo - tam cpp failams nereikia - statinis_pasirašymas „veikia“ tik kompiliavimo metu

 using namespace std::literals; namespace STANDARD { constexpr inline auto compiletime_static_string_view_constant() { // make and return string view literal // will stay the same for the whole application lifetime // will exhibit standard and expected interface // will be usable at both // runtime and compile time // by value semantics implemented for you auto when_needed_ = "compile time"sv; return when_needed_ ; } }; 

Tai yra tinkamas ir teisinis C + + piliečio standartas. Jis gali būti lengvai įtrauktas į bet kurį ir visus std :: algoritmus, konteinerius, komunalines paslaugas ir pan. Pavyzdžiui:

 // test the resilience auto return_by_val = []() { auto return_by_val = []() { auto return_by_val = []() { auto return_by_val = []() { return STANDARD::compiletime_static_string_view_constant(); }; return return_by_val(); }; return return_by_val(); }; return return_by_val(); }; // actually a run time _ASSERTE(return_by_val() == "compile time"); // compile time static_assert( STANDARD::compiletime_static_string_view_constant() == "compile time" ); 

Mėgaukitės „Standard C ++“

1
18 авг. Chef Gladiator atsakymas 18 rug. 2018-08-18 09:36 '18 at 9:36 pm 2018-08-18 09:36

Žr. Kitus klausimus, susijusius su žymėmis, arba Užduoti klausimą