Inicjalizować zmienne statyczne w klasie C++?

Zauważyłem, że niektóre z moich funkcji w klasie nie mają dostępu do obiektu, więc zrobiłem je static. Wtedy kompilator powiedział mi, że wszystkie zmienne, do których mają dostęp, muszą być również statyczne – cóż, na razie całkiem zrozumiałe. Mam kilka zmiennych typu string, takich jak

string RE_ANY = "([^\\n]*)";
string RE_ANY_RELUCTANT = "([^\\n]*?)";

I tak dalej w klasie. Stworzyłem je wszystkie static const, ponieważ nigdy się nie zmieniają. Jednak mój program kompiluje się tylko wtedy, gdy przeniosę je z klasy: w przeciwnym razie MSVC++2010 narzeka " tylko statyczne stałe zmienne całkowe mogą być inicjalizowane w ramach klasy".

To niefortunne. Czy istnieje jakieś obejście? Chciałbym zostawić je w klasie, do której należą.
Author: jww, 2011-02-16

9 answers

Nie mogą być inicjowane wewnątrz klasy, ale mogą być inicjowane poza klasą, w pliku źródłowym:

// inside the class
class Thing {
    static string RE_ANY;
    static string RE_ANY_RELUCTANT;
};

// in the source file
string Thing::RE_ANY = "([^\\n]*)";
string Thing::RE_ANY_RELUCTANT = "([^\\n]*?)";

Update

Właśnie zauważyłem pierwszą linijkę twojego pytania-ty Nie chcesz tworzyć te funkcje static, ty chcesz je tworzyć const. Uczynienie ich static oznacza, że nie są już powiązane z obiektem (więc nie mogą uzyskać dostępu do żadnych niestatycznych elementów), a uczynienie ich statycznymi oznacza, że będą one współdzielone ze wszystkimi obiektami tego obiektu Typ. To może nie być to, czego chcesz. Tworzenie ich const oznacza po prostu, że nie mogą modyfikować żadnych członków, ale nadal mają do nich dostęp.

 102
Author: Mike Seymour,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-16 17:41:13

Mike Seymour dał ci właściwą odpowiedź, ale dodam...
C++ pozwala zadeklarować i zdefiniować w ciele klasy tylko Statyczne typy całkowalne , Jak mówi kompilator. Więc rzeczywiście można zrobić:

class Foo
{
    static const int someInt = 1;
    static const short someShort = 2;
    // etc.
};

I nie możesz tego zrobić z żadnym innym typem, w takim przypadku powinieneś zdefiniować je w swoim .plik cpp.

 25
Author: Santiago V.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-16 19:03:44

Statyczne zmienne członkowskie muszą być zadeklarowane w klasie, a następnie zdefiniowane poza nią!

Nie ma obejścia, wystarczy umieścić ich faktyczną definicję w pliku źródłowym.


Z twojego opisu wynika, że nie używasz zmiennych statycznych we właściwy sposób. Jeśli nigdy się nie zmienią, powinieneś zamiast tego użyć zmiennej constant, ale twój opis jest zbyt ogólny, aby powiedzieć coś więcej.

Statyczne zmienne członkowskie zawsze mają tę samą wartość dla każdej instancji twojej klasy: jeśli zmienisz statyczną zmienną jednego obiektu, zmieni się ona również dla wszystkich innych obiektów (i w rzeczywistości możesz również uzyskać do nich dostęp bez instancji klasy-ie: obiekt).

 15
Author: peoro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-16 17:31:39

Od C++11 można to zrobić wewnątrz klasy z constexpr.

class stat {
    public:
        // init inside class
        static constexpr double inlineStaticVar = 22;
};

Zmienna może być teraz dostępna za pomocą:

stat::inlineStaticVar
 14
Author: 0ax1,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-02 09:36:54

Uważam, że warto dodać, że zmienna statyczna nie jest tym samym, co zmienna stała.

Używanie zmiennej stałej w klasie

struct Foo{
    const int a;
    Foo(int b) : a(b){}
}

And we would declare it like like so

fooA = new Foo(5);
fooB = new Foo(10);
// fooA.a = 5;
// fooB.a = 10;

Dla zmiennej statycznej

struct Bar{
    static int a;
    Foo(int b){
        a = b;
    }
}
Bar::a = 0; // set value for a

Który jest używany tak

barA = new Bar(5);
barB = new Bar(10);
// barA.a = 10;
// barB.a = 10;
// Bar::a = 10;
Widzisz, co się tu dzieje. Zmienna stała, która jest instancjonowana wraz z każdą instancją Foo, ponieważ foo jest instancjonowane, ma osobną wartość dla każdej instancji Foo i nie może być zmieniona przez Foo w ogóle.

Gdzie jak w przypadku Bar, ich jest tylko jedna wartość dla Bar:: a bez względu na to, ile instancji Bar jest wykonanych. Wszystkie mają tę wartość, Możesz również uzyskać do niej dostęp, ponieważ są dowolnymi wystąpieniami paska. Zmienna statyczna również przestrzega reguł dla public/private, więc można sprawić, że tylko instancje Bar mogą odczytać wartość Bar:: a;

 9
Author: thecoshman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-16 17:44:50

Tylko dodać do innych odpowiedzi. Aby zainicjować złożony statyczny element , możesz to zrobić w następujący sposób:

Zadeklaruj swojego statycznego członka jak zwykle.

// myClass.h
class myClass
{
static complexClass s_complex;
//...
};

Zrób małą funkcję, aby zainicjować klasę, jeśli nie jest to trywialne. Zostanie to wywołane tylko raz, gdy statyczny członek zostanie zainicjowany. (Zauważ, że zostanie użyty Konstruktor kopiujący complexClass, więc powinien być dobrze zdefiniowany).

//class.cpp    
#include myClass.h
complexClass initFunction()
{
    complexClass c;
    c.add(...);
    c.compute(...);
    c.sort(...);
    // Etc.
    return c;
}

complexClass myClass::s_complex = initFunction();
 6
Author: Sergio Basurco,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-01 09:17:50

Jeśli twoim celem jest zainicjowanie zmiennej statycznej w pliku nagłówkowym (zamiast *.plik cpp, który możesz chcieć, jeśli trzymasz się idiomu "tylko nagłówek"), możesz obejść problem inicjalizacji za pomocą szablonu. Statyczne zmienne template mogą być inicjowane w nagłówku, bez powodowania definiowania wielu symboli.

Zobacz tutaj przykład:

Statyczna inicjalizacja członka w szablonie klasy

 2
Author: Mark Lakata,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:25

Opcjonalnie Przenieś wszystkie stałe do .plik cpp bez deklaracji w .plik H. Użyj anonimowej przestrzeni nazw, aby uczynić je niewidocznymi poza modułem cpp.

// MyClass.cpp

#include "MyClass.h"

// anonymous namespace
namespace
{
    string RE_ANY = "([^\\n]*)";
    string RE_ANY_RELUCTANT = "([^\\n]*?)";
}

// member function (static or not)
bool MyClass::foo()
{
    // logic that uses constants
    return RE_ANY_RELUCTANT.size() > 0;
}
 1
Author: RuslanK,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-11 12:02:27

Niektóre odpowiedzi wydają się byćmylące trochę.

Nie musisz

  • przypisanie wartości do obiektu statycznego podczas inicjalizacji przypisanie wartości jest opcjonalne .
  • utwórz kolejny plik .cpp aby go zainicjować, można to zrobić tylko w plikunagłówka .

#ifndef CLASS_A_H
#define CLASS_A_H
#include <string>
class A
{
private:
    static std::string str;
    static int x;
};
// Initialize with no values
std::string A::str;
int A::x;
// Initialize with values
//std::string A::str = "SO!";
//int A::x = 900;
#endif
 0
Author: X Stylish,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-11 18:30:32