Słowo kluczowe statyczne i jego różne zastosowania w C++

Słowo kluczowe static jest takie, które ma kilka znaczeń w C++, które uważam za bardzo mylące i nigdy nie mogę pochylić umysłu wokół tego, jak jego rzeczywiście ma działać.

Z tego, co rozumiem, istnieje static Czas przechowywania, co oznacza, że trwa on przez cały czas życia programu w przypadku globalnego, ale gdy mówimy o lokalnym, oznacza to, że domyślnie jest to zero inicjowane.

Standard C++ mówi to dla członków danych klasy ze słowem kluczowym static:

3.7.1 statyczny czas przechowywania [basic.stc.static]

3 słowo kluczowe static może być użyte do zadeklarowania zmiennej lokalnej o statycznym czasie przechowywania.

4 słowo kluczowe static zastosowane do elementu danych klasy w definicji klasy daje statyczny czas przechowywania elementu danych.

Co to znaczy z zmienną lokalną ? Czy to zmienna lokalna funkcji? Ponieważ istnieje również to, że gdy deklarujesz funkcję lokalną jako static że jest inicjalizowana tylko raz, przy pierwszym wejściu do tej funkcji.

Mówi również tylko o czasie przechowywania w odniesieniu do członków klasy, co z tym, że nie jest to specyficzne dla instancji, to również własność static nie? A może jest to czas przechowywania?

A teraz sprawa z static i zakresem plików? Czy uważa się, że wszystkie zmienne globalne mają domyślnie statyczny czas przechowywania danych? Co następuje (z sekcji 3.7.1) wydaje się wskazywać tak:

1 Wszystkie zmienne, które nie mają dynamicznego czasu przechowywania, nie mają czasu przechowywania wątku i są Nie lokalne mają statyczny czas przechowywania. Przechowywanie tych podmiotów powinno trwać przez czas trwania programu (3.6.2, 3.6.3)

Jak static odnosi się do powiązania zmiennej?

To całe static słowo kluczowe jest wręcz mylące, czy ktoś może wyjaśnić różne jego zastosowania w języku angielskim, a także powiedzieć mi kiedy zainicjować static klasę członek?

 157
Author: Tony The Lion, 2013-03-06

9 answers

Zmienne:

static zmienne istnieją dla "życia" jednostki translacji, która jest zdefiniowana w, oraz:

  • Jeśli znajduje się w obszarze przestrzeni nazw (tj. poza funkcjami i klasami), to nie można do niego uzyskać dostępu z żadnej innej jednostki tłumaczeniowej. Jest to znane jako "wewnętrzne powiązanie" lub "statyczny czas przechowywania". (Dont ' zrobić to w nagłówkach, to po prostu straszny pomysł, kończy się z oddzielną zmienną w każdej jednostce tłumaczenia, co jest szalone mylące)
  • jeśli jest zmienną w funkcji , Nie można do niej uzyskać dostępu spoza funkcji, tak jak do każdej innej zmiennej lokalnej. (to jest lokal, o którym wspominali)
  • Członkowie klasy nie mają ograniczonego zakresu ze względu na static, ale mogą być adresowane zarówno z klasy, jak I instancji(jak std::string::npos). [Uwaga: możesz zadeklarować statyczne członkowie w klasie, ale zazwyczaj powinny one być zdefiniowane w jednostce translacyjnej (pliku cpp) i jako takie, jest tylko jeden na klasę]

Miejsce jako kod:

static std::string namespaceScope = "Hello";
void foo() {
    static std::string functionScope= "World";
}
struct A {
   static std::string classScope = "!";
};

Zanim jakakolwiek funkcja w jednostce tłumaczenia zostanie wykonana (prawdopodobnie po main rozpoczęła wykonywanie), zmienne o statycznym czasie przechowywania (zakres przestrzeni nazw) w tej jednostce tłumaczenia będą "stałe inicjalizowane" (do constexpr, gdzie to możliwe, lub zero w przeciwnym razie), a następnie nie-lokalne są "dynamicznie inicjowane" poprawnie w kolejności, w jakiej są zdefiniowane w jednostce tłumaczenia (dla rzeczy takich jak std::string="HI";, które aren ' t constexpr). Na koniec, statyka function-local zostanie zainicjalizowana przy pierwszym "dotarciu" do linii, w której są zadeklarowane. Wszystkie zmienne static zniszczone w odwrotnej kolejności inicjalizacji.

Najprostszym sposobem na uzyskanie tego wszystkiego jest przekształcenie wszystkich statycznych zmiennych, które nie są constexpr zainicjalizowane w statyczne lokalne funkcje, co upewnia się, że wszystkie statyki/globale są zainicjowane poprawnie, gdy próbujesz ich użyć bez względu na wszystko, zapobiegając w ten sposób statyczne fiasko zlecenia inicjalizacji .

T& get_global() {
    static T global = initial_value();
    return global;
}

Bądź ostrożny, ponieważ gdy specyfikacja mówi, że zmienne przestrzeni nazw-zakresu mają domyślnie "statyczny czas przechowywania", oznaczają one "żywotność jednostki tłumaczenia", ale to oznacza a nie, że nie można uzyskać do niego dostępu poza plikiem.

Funkcje

Znacznie prostsze, {[3] } jest często używane jako funkcja członka klasy i bardzo rzadko używane do funkcji wolnostojącej.

Statyczny funkcja member różni się od zwykłej funkcji member tym, że może być wywołana bez instancji klasy, A ponieważ nie ma instancji, nie może uzyskać dostępu do niestatycznych członków klasy. Zmienne statyczne są przydatne, gdy chcesz mieć funkcję dla klasy, która zdecydowanie absolutnie nie odnosi się do żadnych członków instancji, lub do zarządzania zmiennymi składowymi static.

struct A {
    A() {++A_count;}
    A(const A&) {++A_count;}
    A(A&&) {++A_count;}
    ~A() {--A_count;}

    static int get_count() {return A_count;}
private:
    static int A_count;
}

int main() {
    A var;

    int c0 = var.get_count(); //some compilers give a warning, but it's ok.
    int c1 = A::get_count(); //normal way
}

A static funkcja swobodna oznacza, że funkcja ta nie będzie odwoływana przez żadną inną jednostkę translacji, oraz w ten sposób linker może go całkowicie zignorować. Ma to niewielką liczbę celów:

  • Może być używany w pliku cpp, aby zagwarantować, że funkcja nie jest używana z żadnego innego pliku.
  • można umieścić w nagłówku, a każdy plik będzie miał własną kopię funkcji. Nie przydatne, ponieważ inline robi prawie to samo.
  • przyspiesza czas połączenia, redukując pracę
  • może umieścić funkcję o tej samej nazwie w każdej jednostce tłumaczeniowej, a wszystkie mogą robić różne rzeczy. Na przykład, możesz umieścić static void log(const char*) {} w każdym pliku cpp i każdy z nich może zalogować się w inny sposób.
 111
Author: Mooing Duck,
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-06-13 15:44:14

Statyczny czas przechowywania oznacza, że zmienna znajduje się w tym samym miejscu w pamięci przez cały okres życia programu.

Połączenie jest prostopadłe do tego.

Myślę, że to najważniejsze rozróżnienie, jakie możesz zrobić. zrozum to, a reszta, jak również zapamiętanie tego, powinna przyjść łatwo (nie zwracając się bezpośrednio do @ Tony, ale ktokolwiek może to przeczytać w przyszłości).

Słowo kluczowe static może być użyte do oznaczenia powiązań wewnętrznych i statycznych przechowywanie, ale w istocie są one różne.

Co to znaczy ze zmienną lokalną? Czy to zmienna lokalna funkcji?

Tak. Niezależnie od tego, kiedy zmienna zostanie zainicjalizowana (przy pierwszym wywołaniu funkcji i gdy ścieżka wykonania osiągnie punkt deklaracji), będzie ona znajdować się w tym samym miejscu w pamięci przez cały okres istnienia programu. W tym przypadku static daje statyczne przechowywanie.

A teraz sprawa z zakresem statycznym i plikowym? Czy wszystkie zmienne globalne, które domyślnie mają statyczny czas przechowywania danych?

Tak, wszystkie globale mają z definicji statyczny czas przechowywania (teraz, gdy wyjaśniliśmy, co to oznacza). ale zmienne w przestrzeni nazw nie są deklarowane przez static, ponieważ dałoby im to wewnętrzne powiązanie, więc zmienna na jednostkę tłumaczenia.

Jak statyka odnosi się do powiązania zmiennej?

Daje wewnętrzne powiązanie zmiennych z przestrzenią nazw. Informatyka nadaje członkom i zmiennym lokalnym statyczny czas przechowywania.

Rozwińmy to wszystko:

//

static int x; //internal linkage
              //non-static storage - each translation unit will have its own copy of x
              //NOT A TRUE GLOBAL!

int y;        //static storage duration (can be used with extern)
              //actual global
              //external linkage
struct X
{
   static int x;     //static storage duration - shared between classes
};

void foo()
{
   static int x;     //static storage duration - shared between calls
}

To całe statyczne słowo kluczowe jest wręcz mylące

Zdecydowanie, chyba, że jesteś z tym zaznajomiony. :) Starając się uniknąć dodawania nowych słów kluczowych do języka, Komitet ponownie użył tego, IMO, w tym celu-zamieszanie. Jest używany do oznaczenia różnych rzeczy(mogę powiedzieć, prawdopodobnie przeciwstawnych rzeczy).
 53
Author: Luchian Grigore,
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
2013-03-05 23:23:15

To całkiem proste. Jeśli zadeklarujesz zmienną jako statyczną w zakresie funkcji, jej wartość zostanie zachowana między kolejnymi wywołaniami tej funkcji. Więc:

int myFun()
{
static int i=5;
i++;
return i;
}
int main()
{
printf("%d", myFun());
printf("%d", myFun());
printf("%d", myFun());
}

Wyświetli 678 zamiast 666, ponieważ zapamiętuje zwiększoną wartość.

Jeśli chodzi o statyczne elementy, zachowują one swoją wartość między instancjami klasy. Zatem następujący kod:

struct A
{
static int a;
};
int main()
{
A first;
A second;
first.a = 3;
second.a = 4;
printf("%d", first.a);
}

Wydrukuje 4, ponieważ pierwszy.a i drugie.a są zasadniczo tą samą zmienną. Co do inicjalizacja, zobacz to pytanie.

 18
Author: Maciej Stachowski,
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:10:39

Aby wyjaśnić pytanie, chciałbym raczej kategoryzować użycie słowa kluczowego' static ' w trzech różnych formach:

(A). zmienne

(B). funkcje

(C). zmienne członkowskie / funkcje klas

Wyjaśnienie poniżej dla każdego z poddziałów:

(A) słowo kluczowe' static ' dla zmiennych

Ten może być trochę trudne, ale jeśli wyjaśnione i zrozumiane prawidłowo, to jest ładny proste.

Aby to wyjaśnić, najpierw warto wiedzieć o Zakres, czas trwania i powiązania zmiennych, bez których rzeczy są zawsze trudne do zobaczenia przez mroczne pojęcie słowa kluczowego staic

1. Scope : określa, gdzie w pliku zmienna jest dostępna. Może być dwóch typów: (i) Local lub Block Scope. (ii) zasięg globalny

2. Duration : określa kiedy zmienna jest tworzona i zniszczone. Ponownie jest to dwa typy: (i) Automatyczny czas przechowywania (dla zmiennych o zasięgu lokalnym lub blokowym). (ii) statyczny czas przechowywania (dla zmiennych o zasięgu globalnym lub zmiennych lokalnych (w funkcji lub w bloku kodu) ze specyfikatorem statyczny ).

3. Linkage : określa, czy zmienna może być dostępna (lub połączona) w innym pliku. I znowu (i na szczęście) jest to dwa typy: (i) linkowanie wewnętrzne (dla zmiennych mając zakres bloku i globalny Zakres / Zakres pliku / Globalny zakres przestrzeni nazw) (ii) zewnętrzne powiązanie (dla zmiennych mających tylko Zakres Globalny / zakres pliku / Globalny zakres przestrzeni nazw)

Poniższy przykład pozwala lepiej zrozumieć zmienne globalne i lokalne (Brak zmiennych lokalnych o statycznym czasie przechowywania):

//main file
#include <iostream>

int global_var1; //has global scope
const global_var2(1.618); //has global scope

int main()
{
//these variables are local to the block main.
//they have automatic duration, i.e, they are created when the main() is 
//  executed and destroyed, when main goes out of scope
 int local_var1(23);
 const double local_var2(3.14);

 {
/* this is yet another block, all variables declared within this block are 
 have local scope limited within this block. */
// all variables declared within this block too have automatic duration, i.e, 
/*they are created at the point of definition within this block,
 and destroyed as soon as this block ends */
   char block_char1;
   int local_var1(32) //NOTE: this has been re-declared within the block, 
//it shadows the local_var1 declared outside

 std::cout << local_var1 <<"\n"; //prints 32

  }//end of block
  //local_var1 declared inside goes out of scope

 std::cout << local_var1 << "\n"; //prints 23

 global_var1 = 29; //global_var1 has been declared outside main (global scope)
 std::cout << global_var1 << "\n"; //prints 29
 std::cout << global_var2 << "\n"; //prints 1.618

 return 0;
}  //local_var1, local_var2 go out of scope as main ends
//global_var1, global_var2 go out of scope as the program terminates 
//(in this case program ends with end of main, so both local and global
//variable go out of scope together

Teraz pojawia się pojęcie powiązania. Gdy zmienna globalna zdefiniowana w jednym pliku jest przeznaczona do użycia w innym pliku, zmienna odgrywa ważną rolę.

Powiązanie zmiennych globalnych jest określone przez słowa kluczowe: (i) static , oraz (ii) extern

( Teraz masz Wyjaśnienie ; -))

Słowo kluczowe statyczne może być stosowane do zmiennych o zasięgu lokalnym i globalnym i w obu przypadkach oznaczają one różne rzeczy. Najpierw wyjaśnię użycie słowa kluczowego 'static' w zmiennych o zasięgu globalnym (gdzie wyjaśniam również użycie słowa kluczowego 'extern'), a później dla te o zasięgu lokalnym.

1. Statyczne słowo kluczowe dla zmiennych o zasięgu globalnym

Zmienne globalne mają statyczny czas trwania, co oznacza, że nie wychodzą poza zakres, gdy kończy się dany blok kodu (np. main ()), w którym jest używany . W zależności od powiązania, mogą być dostępne tylko w tym samym pliku, w którym są zadeklarowane (dla statycznej zmiennej globalnej), lub poza plikiem, nawet poza plikiem, w którym są zadeklarowane (extern typu global zmienne)

W przypadku zmiennej globalnej posiadającej specyfikator extern i jeśli ta zmienna jest dostępna poza plikiem, w którym została zainicjowana, musi być zadeklarowana w pliku, w którym jest używana, podobnie jak funkcja musi być zadeklarowana w forward, jeśli jej definicja znajduje się w innym Pliku niż ten, w którym jest używana.

Natomiast, jeśli zmienna globalna ma słowo kluczowe statyczne, nie może być użyta w pliku, poza którym została zadeklarowana.

(zobacz przykład poniżej dla wyjaśnienia)

Eg:

//main2.cpp
 static int global_var3 = 23;  /*static global variable, cannot be                            
                                accessed in anyother file */
 extern double global_var4 = 71; /*can be accessed outside this file                  linked to main2.cpp */
 int main() { return 0; }

Main3.cpp

//main3.cpp
#include <iostream>

int main()
{
   extern int gloabl_var4; /*this variable refers to the gloabal_var4
                            defined in the main2.cpp file */
  std::cout << global_var4 << "\n"; //prints 71;

  return 0;
}

Teraz każda zmienna w c++ może być albo const albo non-const i dla każdego 'const-Ness' otrzymujemy dwa przypadki domyślnego powiązania c++, w przypadku gdy nie podano żadnego:

(i) jeśli zmienna globalna nie jest const, jej powiązanie jest domyślnie extern , tzn. zmienna globalna Nie-const może być dostępna w innej .plik cpp poprzez deklarację forward używając słowa kluczowego extern (w innych words, non const global variables have external linkage (with static duration of course)). Również użycie słowa kluczowego extern w oryginalnym pliku, w którym zostało zdefiniowane, jest zbędne. W tym przypadku aby zmienna globalna Nie-const była niedostępna dla pliku zewnętrznego, należy użyć specyfikatora 'static' przed typem zmiennej.

(ii) jeśli zmienna globalna jest const, jej połączenie jest domyślnie statyczne , tzn. plik inny niż ten, w którym jest zdefiniowany, (innymi słowy, zmienne globalne const mają wewnętrzne powiązania (ze statycznym czasem trwania)). Również użycie statycznego słowa kluczowego, aby zapobiec dostępowi do zmiennej globalnej const w innym pliku, jest zbędne. Proszę., aby zmienna globalna const miała powiązania zewnętrzne, należy użyć specyfikatora "extern" przed typem zmiennej

Oto podsumowanie globalnych zmiennych zakresu z różnymi linkages

//globalVariables1.cpp 

// defining uninitialized vairbles
int globalVar1; //  uninitialized global variable with external linkage 
static int globalVar2; // uninitialized global variable with internal linkage
const int globalVar3; // error, since const variables must be initialized upon declaration
const int globalVar4 = 23; //correct, but with static linkage (cannot be accessed outside the file where it has been declared*/
extern const double globalVar5 = 1.57; //this const variable ca be accessed outside the file where it has been declared

Następnie zbadamy, jak zachowują się powyższe zmienne globalne, gdy są dostępne w innym pliku.

//using_globalVariables1.cpp (eg for the usage of global variables above)

// Forward declaration via extern keyword:
 extern int globalVar1; // correct since globalVar1 is not a const or static
 extern int globalVar2; //incorrect since globalVar2 has internal linkage
 extern const int globalVar4; /* incorrect since globalVar4 has no extern 
                         specifier, limited to internal linkage by
                         default (static specifier for const variables) */
 extern const double globalVar5; /*correct since in the previous file, it 
                           has extern specifier, no need to initialize the
                       const variable here, since it has already been
                       legitimately defined perviously */

2. Statyczne słowo kluczowe dla zmiennych o zasięgu lokalnym

Wcześniej wspomniałem, że zmienne z lokalnym zakresem mają Automatyczny czas trwania, tzn. pojawiają się po wprowadzeniu bloku (czy to zwykły, czy blok funkcyjny) i przestają istnieć po jego zakończeniu, w skrócie, zmienne o zasięgu lokalnym mają automatyczny czas trwania zmienne czasu trwania automatycznego (i Obiekty) nie mają powiązania, co oznacza, że nie są widoczne poza blokiem kodu.

Jeśli do zmiennej lokalnej w bloku zostanie zastosowany specyfikator static, to zmienia czas trwania zmiennej z automatyczny na statyczny , a jej czas życia to cały czas trwania programu, co oznacza, że ma stałą lokalizację pamięci i jej wartość jest inicjalizowana tylko raz przed uruchomieniem programu, jak wspomniano w cpp odsyłacz (inicjalizacja nie powinna być mylona z przypisaniem)

Spójrzmy na przykład.

//localVarDemo.cpp
 #include <iostream>

 int localNextID()
{
  int tempID = 1;  //tempID created here
  return tempID++; //copy of tempID returned and tempID incremented to 2
} //tempID destroyed here, hence value of tempID lost

int newNextID()
{
  static int newID = 0;//newID has static duration, with internal linkage
  return newID++; //copy of newID returned and newID incremented by 1
}  //newID doesn't get destroyed here :-)


int main()
{
  int employeeID1 = nextID();  //employeeID1 = 1
  int employeeID2 = nextID();  // employeeID2 = 1 again (not desired)
  int employeeID3 = newNextID(); //employeeID3 = 0;
  int employeeID4 = newNextID(); //employeeID4 = 1;
  int employeeID5 = newNextID(); //employeeID5 = 2;
  return 0;
}

To kończy moje wyjaśnienie dla statycznego słowa kluczowego zastosowanego do zmiennych. pheww!!!

B. słowo kluczowe' static ' używane dla funkcji

Jeśli chodzi o funkcje, słowo kluczowe statyczne ma proste znaczenie. Tutaj odnosi się do powiązania funkcji Zwykle wszystkie funkcje zadeklarowane w pliku cpp mają zewnętrzne powiązanie przez domyślnie, tzn. funkcja zdefiniowana w jednym pliku może być użyta w innym pliku cpp poprzez deklarację forward.

Użycie statycznego słowa kluczowego przed deklaracją funkcji ogranicza jej powiązanie do wewnętrznego , tzn. funkcja statyczna nie może być używana w pliku poza jej definicją.

C. słowo kluczowe Staitc używane dla zmiennych członkowskich i funkcji klas

1. 'static' słowo kluczowe dla zmiennych członkowskich klas

Zaczynam bezpośrednio od przykład tutaj

#include <iostream>

class DesignNumber
{
  private:

      static int m_designNum;  //design number
      int m_iteration;     // number of iterations performed for the design

  public:
    DesignNumber() {     }  //default constructor

   int  getItrNum() //get the iteration number of design
   {
      m_iteration = m_designNum++;
      return m_iteration;
   }
     static int m_anyNumber;  //public static variable
};
int DesignNumber::m_designNum = 0; // starting with design id = 0
                     // note : no need of static keyword here
                     //causes compiler error if static keyword used
int DesignNumber::m_anyNumber = 99; /* initialization of inclass public 
                                    static member  */
enter code here

int main()
{
   DesignNumber firstDesign, secondDesign, thirdDesign;
   std::cout << firstDesign.getItrNum() << "\n";  //prints 0
   std::cout << secondDesign.getItrNum() << "\n"; //prints 1
   std::cout << thirdDesign.getItrNum() << "\n";  //prints 2

   std::cout << DesignNumber::m_anyNumber++ << "\n";  /* no object
                                        associated with m_anyNumber */
   std::cout << DesignNumber::m_anyNumber++ << "\n"; //prints 100
   std::cout << DesignNumber::m_anyNumber++ << "\n"; //prints 101

   return 0;
}

W tym przykładzie zmienna statyczna m_designNum zachowuje swoją wartość i ta pojedyncza prywatna zmienna składowa (ponieważ jest statyczna) jest współdzielona b/W wszystkich zmiennych typu obiektu DesignNumber

Podobnie jak inne zmienne członkowskie, statyczne zmienne klasy nie są powiązane z żadnym obiektem klasy, co jest demonstrowane przez drukowanie anyNumber w głównej funkcji

Const vs non-const statyczne zmienne członkowskie w Klasa

(i) zmienne statyczne klasy non-const W poprzednim przykładzie statyczne elementy (zarówno publiczne, jak i prywatne) nie były stałymi. Norma ISO zabrania inicjalizacji w klasie nie-const statycznych elementów. Tak jak w poprzednim przykładzie, muszą być initalizowane po definicji klasy, z zastrzeżeniem, że słowo kluczowe statyczne musi zostać pominięte

(ii) const-statyczne zmienne członkowskie klasy jest to proste i idzie z konwencja inicjalizacji innych zmiennych składowych const, tzn. statyczne zmienne składowe klasy mogą być inicjalizowane w punkcie deklaracji i mogą być inicjalizowane na końcu deklaracji klasy z jednym zastrzeżeniem, że słowo kluczowe const musi być dodane do statycznego elementu podczas inicjalizacji po definicji klasy.

Zalecałbym jednak inicjalizację statycznych zmiennych składowych const w punkcie deklaracji. To idzie z standard C++ convention i sprawia, że kod wygląda czystsze

Więcej przykładów statycznych zmiennych członkowskich w klasie znajdziesz w poniższym linku z learncpp.com http://www.learncpp.com/cpp-tutorial/811-static-member-variables/

2. 'static' keyword for member function of classes

Tak jak zmienne składowe klas mogą być statyczne, tak też funkcje składowe klas mogą być statyczne. Normalne funkcje składowe klas są zawsze związane z obiektem o Typ klasowy. W przeciwieństwie do tego, statyczne funkcje członkowskie klasy nie są powiązane z żadnym obiektem klasy, tzn. nie mają *tego wskaźnika.

Po drugie, ponieważ statyczne funkcje klasy nie mają * tego wskaźnika, mogą być wywołane za pomocą nazwy klasy i operatora rozdzielczości zakresu w głównej funkcji (ClassName::functionName ();)

Po Trzecie statyczne funkcje klasy mogą mieć dostęp tylko do statycznych zmiennych klasy, ponieważ niestatyczne zmienne klasy klasy musi należeć do obiektu klasy.

Więcej przykładów na statyczne funkcje członka w klasie znajdziesz w poniższym linku z learncpp.com

Http://www.learncpp.com/cpp-tutorial/812-static-member-functions/

 17
Author: gajendra,
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-09-27 18:12:06

Zmienne statyczne są współdzielone pomiędzy każdą instancją klasy, zamiast każdej klasy posiadającej własną zmienną.

class MyClass
{
    public:
    int myVar; 
    static int myStaticVar;
};

//Static member variables must be initialized. Unless you're using C++11, or it's an integer type,
//they have to be defined and initialized outside of the class like this:
MyClass::myStaticVar = 0;

MyClass classA;
MyClass classB;

Każda instancja 'MyClass' ma swój własny 'myVar' , ale ma ten sam 'myStaticVar'. W rzeczywistości nie potrzebujesz nawet instancji MyClass, aby uzyskać dostęp do 'myStaticVar' , a możesz uzyskać do niej dostęp poza klasą w następujący sposób:

MyClass::myStaticVar //Assuming it's publicly accessible.

Gdy jest używana wewnątrz funkcji jako zmienna lokalna (a nie jako zmienna klasy), słowo kluczowe statyczne robi coś inaczej. Pozwala na utworzenie zmiennej trwałej, bez podawania zasięgu globalnego.

int myFunc()
{
   int myVar = 0; //Each time the code reaches here, a new variable called 'myVar' is initialized.
   myVar++;

   //Given the above code, this will *always* print '1'.
   std::cout << myVar << std::endl;

   //The first time the code reaches here, 'myStaticVar' is initialized. But ONLY the first time.
   static int myStaticVar = 0;

   //Each time the code reaches here, myStaticVar is incremented.
   myStaticVar++;

   //This will print a continuously incrementing number,
   //each time the function is called. '1', '2', '3', etc...
   std::cout << myStaticVar << std::endl;
}

Jest zmienną globalną pod względem trwałości... ale bez bycia globalnym w zakresie / dostępności.

Możesz także mieć statyczne funkcje Członkowskie. Funkcje statyczne są zasadniczo funkcjami nieczłonkowymi, ale wewnątrz przestrzeni nazw klasy i z prywatnym dostępem do członków klasy.

class MyClass
{
    public:
    int Func()
    {
        //...do something...
    }

    static int StaticFunc()
    {
        //...do something...
    }
};

int main()
{
   MyClass myClassA;
   myClassA.Func(); //Calls 'Func'.
   myClassA.StaticFunc(); //Calls 'StaticFunc'.

   MyClass::StaticFunc(); //Calls 'StaticFunc'.
   MyClass::Func(); //Error: You can't call a non-static member-function without a class instance!

   return 0;
}

Kiedy wywołujesz funkcję member, istnieje ukryty parametr o nazwie 'this' , czyli wskaźnik do instancji klasy wywołującej funkcję. Static member functions don ' t have that hidden parameter... są one wywoływane bez instancji klasy, ale nie mogą również uzyskać dostępu do niestatycznych zmiennych klasy, ponieważ nie mają "tego" wskaźnika do pracy. Nie są wywoływane na żadnej konkretnej instancji klasowej.

 8
Author: Jamin Grey,
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
2016-09-09 15:33:54

Jeśli zadeklarujesz zmienną static w obszarze pliku, to zmienna ta jest dostępna tylko w , że konkretny plik(technicznie rzecz biorąc, Jednostka tłumaczenia*, ale nie komplikujmy tego zbytnio). Na przykład:

A.cpp

static int x = 7;

void printax()
{
    cout << "from a.cpp: x=" << x << endl;
}

B.cpp

static int x = 9;

void printbx()
{
    cout << "from b.cpp: x=" << x << endl;
}

Main.cpp:

int main(int, char **)
{
    printax(); // Will print 7
    printbx(); // Will print 9

    return 0;
}

Dla zmiennej local , static oznacza, że zmienna będzie inicjowana zero i zachowuje swoją wartość pomiędzy wywołania:

unsigned int powersoftwo()
{
    static unsigned lastpow;

    if(lastpow == 0)
        lastpow = 1;
    else
        lastpow *= 2;

    return lastpow;
}

int main(int, char **)
{
    for(int i = 0; i != 10; i++)
        cout << "2^" << i << " = " << powersoftwo() << endl;
}

Dla zmiennych klasy oznacza to, że istnieje tylko jedna instancja tej zmiennej, która jest współdzielona pomiędzy wszystkimi członkami tej klasy. W zależności od uprawnień, zmienna może być dostępna spoza klasy, używając jej w pełni kwalifikowanej nazwy.

class Test
{
private:
    static char *xxx;

public:
    static int yyy;

public:
    Test()
    {        
        cout << this << "The static class variable xxx is at address "
             << static_cast<void *>(xxx) << endl;
        cout << this << "The static class variable yyy is at address "
             << static_cast<void *>(&y) << endl;
    }
};

// Necessary for static class variables.
char *Test::xxx = "I'm Triple X!";
int Test::yyy = 0;

int main(int, char **)
{
    Test t1;
    Test t2;

    Test::yyy = 666;

    Test t3;
};

Oznaczenie funkcji nieklasowej jako static sprawia, że funkcja jest dostępna tylko z tego pliku i niedostępna z innych plików.

A.cpp

static void printfilename()
{ // this is the printfilename from a.cpp - 
  // it can't be accessed from any other file
    cout << "this is a.cpp" << endl;
}

B.cpp

static void printfilename()
{ // this is the printfilename from b.cpp - 
  // it can't be accessed from any other file
    cout << "this is b.cpp" << endl;
}

Dla funkcji klasy oznaczenie ich jako static oznacza, że funkcja nie musi być wywoływana na konkretnej instancji obiektu (tzn. nie ma wskaźnika this).

class Test
{
private:
    static int count;

public:
    static int GetTestCount()
    {
        return count;
    };

    Test()
    {
        cout << this << "Created an instance of Test" << endl;
        count++;
    }

    ~Test()
    {
        cout << this << "Destroyed an instance of Test" << endl;
        count--;
    }
};

int Test::count = 0;

int main(int, char **)
{
    Test *arr[10] = { NULL };

    for(int i = 0; i != 10; i++)
        arr[i] = new Test();

    cout << "There are " << Test::GetTestCount() << " instances of the Test class!" << endl;

    // now, delete them all except the first and last!
    for(int i = 1; i != 9; i++)
        delete arr[i];        

    cout << "There are " << Test::GetTestCount() << " instances of the Test class!" << endl;

    delete arr[0];

    cout << "There are " << Test::GetTestCount() << " instances of the Test class!" << endl;

    delete arr[9];

    cout << "There are " << Test::GetTestCount() << " instances of the Test class!" << endl;

    return 0;
}
 7
Author: Nik Bougalis,
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-04-14 14:31:07

Nie jestem programistą C, więc nie mogę dać Ci informacji na temat zastosowań statycznych w programie C, ale jeśli chodzi o programowanie zorientowane obiektowo, static zasadniczo deklaruje zmienną, funkcję lub klasę, aby były takie same przez cały okres życia programu. Weźmy na przykład.

class A
{
public:
    A();
    ~A();
    void somePublicMethod();
private:
    void somePrivateMethod();
};

Kiedy tworzysz tę klasę w swoim głównym, robisz coś takiego.

int main()
{
   A a1;
   //do something on a1
   A a2;
   //do something on a2
}

Te dwie instancje klas są zupełnie różne od siebie i działają niezależnie od siebie nawzajem. Ale gdyby tak odtworzyć klasę A.

class A
{
public:
    A();
    ~A();
    void somePublicMethod();
    static int x;
private:
    void somePrivateMethod();
};

Wróćmy jeszcze raz do głównego.

int main()
{
   A a1;
   a1.x = 1;
   //do something on a1
   A a2;
   a2.x++;
   //do something on a2
}

Wtedy a1 i a2 dzieliłyby tę samą kopię int x, przy czym wszelkie operacje na x w a1 miałyby bezpośredni wpływ na operacje x w a2. Więc gdybym miał to zrobić

int main()
{
   A a1;
   a1.x = 1;
   //do something on a1
   cout << a1.x << endl; //this would be 1
   A a2;
   a2.x++;
   cout << a2.x << endl; //this would be 2 
   //do something on a2
}

Obie instancje klasy A mają wspólne zmienne statyczne i funkcje. Mam nadzieję, że to odpowie na twoje pytanie. Moja ograniczona znajomość C pozwala mi powiedzieć, że definiowanie funkcji lub zmiennej jako statyczny oznacza, że jest widoczny tylko dla pliku, w którym funkcja lub zmienna jest zdefiniowana jako statyczny. Ale na to lepiej odpowie Facet Z "C", a nie ja. C++ pozwala zarówno C, jak i C++ na deklarowanie zmiennych jako statycznych, ponieważ jest całkowicie wstecznie kompatybilny z C.

 1
Author: David Tr,
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
2013-03-05 22:52:18

Co to znaczy ze zmienną lokalną? Czy to zmienna lokalna funkcji?

Yes-nie-globalna, np. zmienna lokalna funkcji.

Ponieważ istnieje również to, że gdy zadeklarujesz funkcję lokalną jako statyczną, jest ona zainicjalizowana tylko raz, to po raz pierwszy wejdzie ona do tej funkcji.

Racja.

Mówi również tylko o czasie przechowywania w odniesieniu do członków klasy, a co z tym, że nie jest to specyficzne dla instancji, to także własność statyczna nr? A może jest to czas przechowywania?

class R { static int a; }; // << static lives for the duration of the program

Czyli wszystkie instancje R dzielą int R::a -- int R::a nigdy nie jest kopiowany.

A teraz sprawa z zakresem statycznym i plikowym?

W rzeczywistości globalny, który ma konstruktor / Destruktor, gdzie jest to właściwe -- inicjalizacja nie jest odroczona do czasu dostępu.

Jak statyka odnosi się do powiązania zmiennej?

Dla funkcji lokalnej jest ona zewnętrzna. Dostęp: Jest on dostępny dla funkcji (chyba, że zwrócisz go).

Dla klasy, to jest zewnętrzne. Dostęp: obowiązują standardowe warunki dostępu (publiczny, chroniony, prywatny).

static może również określać wewnętrzne powiązanie, w zależności od tego, gdzie jest zadeklarowane (plik/przestrzeń nazw).

To całe statyczne słowo kluczowe jest wręcz mylące

Ma zbyt wiele celów w C++.

Czy ktoś może wyjaśnić różne zastosowania tego języka angielskiego, a także powiedzieć mi, kiedy zainicjować członka klasy statycznej?

Jest automatycznie inicjalizowana przed main, jeśli jest załadowana i ma konstruktor. To może brzmieć jak dobra rzecz, ale kolejność inicjalizacji jest w dużej mierze poza Twoją kontrolą, więc skomplikowana inicjalizacja staje się bardzo trudna do utrzymania i chcesz to zminimalizować-jeśli musisz mieć statykę, to funkcjonuj lokalne skale znacznie lepiej w bibliotekach i projektach. Jeśli chodzi o dane o statycznym czasie przechowywania, należy spróbować zminimalizować to projektowania, szczególnie jeśli zmienna (zmienne globalne). Czas inicjalizacji różni się również z wielu powodów-program ładujący i jądro mają pewne sztuczki, aby zminimalizować ślady pamięci i odroczyć inicjalizację, w zależności od danych.

 1
Author: justin,
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
2013-03-05 23:18:49

Static Object: możemy zdefiniować klasy static używając słowa kluczowego static. Kiedy deklarujemy element klasy jako statyczny, oznacza to, że bez względu na to, ile obiektów tej klasy zostanie utworzonych, istnieje tylko jedna kopia elementu statycznego.

Statyczny element jest współdzielony przez wszystkie obiekty klasy. Wszystkie dane statyczne są inicjalizowane do zera podczas tworzenia pierwszego obiektu, jeśli nie ma innej inicjalizacji. Nie możemy umieścić go w definicji klasy, ale można go zainicjować poza klasa, Jak to zrobiono w poniższym przykładzie, poprzez ponowne zadeklarowanie zmiennej statycznej, używając operatora rozdzielczości zakresu::, aby określić, do której klasy należy.

Spróbujmy w poniższym przykładzie zrozumieć pojęcie statycznych elementów danych:

#include <iostream>

using namespace std;

class Box
{
   public:
      static int objectCount;
      // Constructor definition
      Box(double l=2.0, double b=2.0, double h=2.0)
      {
         cout <<"Constructor called." << endl;
         length = l;
         breadth = b;
         height = h;
         // Increase every time object is created
         objectCount++;
      }
      double Volume()
      {
         return length * breadth * height;
      }
   private:
      double length;     // Length of a box
      double breadth;    // Breadth of a box
      double height;     // Height of a box
};

// Initialize static member of class Box
int Box::objectCount = 0;

int main(void)
{
   Box Box1(3.3, 1.2, 1.5);    // Declare box1
   Box Box2(8.5, 6.0, 2.0);    // Declare box2

   // Print total number of objects.
   cout << "Total objects: " << Box::objectCount << endl;

   return 0;
}

Gdy powyższy kod jest kompilowany i wykonywany, daje następujący wynik:

Constructor called.
Constructor called.
Total objects: 2

Static Function Members: Deklarując element funkcji jako statyczny, uniezależniasz go od konkretnego obiektu klasy. Statyczna funkcja składowa może być wywołana nawet wtedy, gdy nie istnieją żadne obiekty klasy, A funkcje statyczne są dostępne tylko przy użyciu nazwy klasy i operatora rozdzielczości zakresu ::.

Funkcja statyczna może uzyskać dostęp tylko do statycznego elementu danych, innych funkcji statycznych i innych funkcji spoza klasy.

Statyczne funkcje Członkowskie mają zakres klasy i nie mają dostępu do tego wskaźnika klasy. Możesz użyć statycznej funkcji członka, aby określ, czy niektóre obiekty klasy zostały utworzone, czy nie.

Spróbujmy w poniższym przykładzie zrozumieć pojęcie statycznych członów funkcji:

#include <iostream>

using namespace std;

class Box
{
   public:
      static int objectCount;
      // Constructor definition
      Box(double l=2.0, double b=2.0, double h=2.0)
      {
         cout <<"Constructor called." << endl;
         length = l;
         breadth = b;
         height = h;
         // Increase every time object is created
         objectCount++;
      }
      double Volume()
      {
         return length * breadth * height;
      }
      static int getCount()
      {
         return objectCount;
      }
   private:
      double length;     // Length of a box
      double breadth;    // Breadth of a box
      double height;     // Height of a box
};

// Initialize static member of class Box
int Box::objectCount = 0;

int main(void)
{

   // Print total number of objects before creating object.
   cout << "Inital Stage Count: " << Box::getCount() << endl;

   Box Box1(3.3, 1.2, 1.5);    // Declare box1
   Box Box2(8.5, 6.0, 2.0);    // Declare box2

   // Print total number of objects after creating object.
   cout << "Final Stage Count: " << Box::getCount() << endl;

   return 0;
}

Gdy powyższy kod jest kompilowany i wykonywany, daje następujący wynik:

Inital Stage Count: 0
Constructor called.
Constructor called.
Final Stage Count: 2
 1
Author: Nima Soroush,
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-05-08 08:49:27