Soruyu açıklığa kavuşturmak için, 'statik' anahtar kelimenin kullanımını üç farklı biçimde kategorize etmek istiyorum:
(A). değişkenler
(B). fonksiyonlar
(C). üye değişkenler / sınıf fonksiyonları
alt başlıkların her biri için açıklama aşağıdaki gibidir:
(A) Değişkenler için 'statik' anahtar kelime
Bu biraz zor olabilir, ancak doğru bir şekilde açıklanır ve anlaşılırsa, oldukça basittir.
Bunu açıklamak için öncelikle değişkenlerin kapsamı, süresi ve bağlantısı hakkında bilgi vermek gerçekten yararlıdır.
1. Kapsam : Dosyanın neresinde erişilebilir olduğuna karar verir. İki tip olabilir: (i) Yerel veya Blok Kapsamı . (ii) Küresel Kapsam
2. Süre : Bir değişkenin ne zaman oluşturulacağını ve yok edileceğini belirler. Yine iki tiptir: (i) Otomatik Saklama Süresi (Yerel veya Blok kapsamı olan değişkenler için). (ii) Statik Depolama Süresi (Genel Kapsamı olan değişkenler veya statik belirleyicili yerel değişkenler (bir işlevde veya bir kod bloğunda) için ).
3. Bağlantı : Bir değişkenin başka bir dosyadan erişilip erişilemeyeceğini (veya bağlanabileceğini) belirler. Yine (ve neyse ki) iki tiptir: (i) Dahili Bağlantı
(Blok Kapsamı ve Global Kapsam / Dosya Kapsamı / Global Ad Alanı kapsamı olan değişkenler için ) (ii) Harici Bağlantı (sadece Global Kapsam / Dosya Kapsamı / Global Ad Alanı Kapsamı)
Düz küresel ve yerel değişkenleri daha iyi anlamak için aşağıdaki örneğe bakalım (statik depolama süresine sahip yerel değişkenler yok):
//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
Şimdi Bağlantı kavramı geliyor. Bir dosyada tanımlanan bir global değişkenin başka bir dosyada kullanılması amaçlandığında, değişkenin bağlantısı önemli bir rol oynar.
Global değişkenlerin bağlantısı şu anahtar kelimelerle belirtilir: (i) statik ve (ii) harici
(Şimdi açıklamayı aldınız)
statik anahtar kelime yerel ve global kapsamdaki değişkenlere uygulanabilir ve her iki durumda da farklı şeyler ifade eder. Önce küresel kapsamdaki değişkenlerde 'statik' anahtar kelime kullanımını açıklayacağım (burada 'extern' anahtar kelimesinin kullanımını da açıklığa kavuşturacağım) ve daha sonra yerel kapsamı olanlar için.
1. Küresel kapsamdaki değişkenler için Statik Anahtar Kelime
Global değişkenler statik süreye sahiptir, yani kullanıldıkları belirli bir kod bloğu (örneğin main ()) sona erdiğinde kapsam dışı kalmazlar. Bağlantıya bağlı olarak, bunlara yalnızca bildirildikleri dosya içinde (statik global değişken için) veya bildirildikleri dosyanın dışında bile (harici tip global değişkenler) erişilebilir.
Extern belirleyicisine sahip bir global değişken söz konusuysa ve bu değişkene, başlatıldığı dosyanın dışında erişiliyorsa, tıpkı bir işlevin iletilmesi gerektiği gibi, kullanıldığı dosyada ileriye doğru bildirilmelidir tanımı, kullanıldığı yerden farklı bir dosyadaysa bildirilir.
Buna karşılık, global değişken statik anahtar kelimeye sahipse, dışında bildirildiği bir dosyada kullanılamaz.
(açıklama için aşağıdaki örneğe bakın)
Örneğin:
//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;
}
şimdi c ++ 'daki herhangi bir değişken bir const veya const olmayan olabilir ve her' const-ness 'için, hiçbiri belirtilmemişse, iki varsayılan c ++ bağlantısı durumu elde ederiz:
(i) Genel bir değişken sabit değilse, bağlantı varsayılan olarak extern'dir , yani sabit olmayan genel değişken, extern anahtar sözcüğü kullanılarak ileri bir bildirimle başka bir .cpp dosyasında erişilebilir (başka bir deyişle, const global olmayan) değişkenler dış bağlantıya sahiptir (statik süre ile). Ayrıca, extern anahtar sözcüğünün tanımlandığı orijinal dosyada kullanılması gereksizdir. Bu durumda , sabit olmayan bir genel değişkeni harici dosyaya erişilemez hale getirmek için, değişken türünden önce 'statik' belirtecini kullanın .
(ii) Genel değişken sabitse, bağlantı varsayılan olarak statiktir , yani sabit genel değişken tanımlandığı yer dışında bir dosyaya erişilemez (başka bir deyişle, sabit genel değişkenler dahili bağlantıya sahiptir (statik süre ile) elbette)). Ayrıca, sabit bir global değişkenin başka bir dosyada erişilmesini önlemek için statik anahtar kelimenin kullanılması gereksizdir. Burada, sabit bir global değişkenin harici bir bağlantıya sahip olması için, değişken türünden önce 'extern' belirtecini kullanın
Çeşitli bağlantılara sahip global kapsam değişkenleri için bir özet
//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
Daha sonra, yukarıdaki küresel değişkenlerin farklı bir dosyaya erişildiğinde nasıl davrandığını araştırıyoruz.
//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. Yerel Kapsamlı değişkenler için Statik Anahtar Kelime
Yerel kapsamdaki değişkenler için statik anahtar kelimeyle ilgili güncellemeler (Ağustos 2019)
Bu ayrıca iki kategoriye ayrılabilir:
(i) bir işlev bloğundaki değişkenler için statik anahtar kelime ve (ii) adsız bir yerel blok içindeki değişkenler için statik anahtar kelime.
(i) bir fonksiyon bloğundaki değişkenler için statik anahtar kelime.
Daha önce, yerel kapsamdaki değişkenlerin otomatik süreye sahip olduğunu, yani blok girildiğinde (normal bir blok olsun, bir fonksiyon bloğu olsun) var olduklarını ve blok bittiğinde, uzun öykü kısa, değişkenlerde var olduklarını belirttim. yerel kapsamda otomatik süre vardır ve otomatik süre değişkenleri (ve nesneler) hiçbir bağlantı yoktur yani kod bloğu dışında görünmez.
Eğer statik belirleyici bir işlev bloğu dahilinde yerel bir değişkene uygulanır, statik otomatik değişkenin süresini değiştirir ve yaşam süresi, sabit bellek konuma sahiptir araçları programının tamamı süresi ve değeri sadece başlatıldı cpp referansında belirtildiği gibi program başlatılmadan önce (başlatma, atama ile karıştırılmamalıdır)
bir örneğe bakalım.
//localVarDemo1.cpp
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 = localNextID(); //employeeID1 = 1
int employeeID2 = localNextID(); // employeeID2 = 1 again (not desired)
int employeeID3 = newNextID(); //employeeID3 = 0;
int employeeID4 = newNextID(); //employeeID4 = 1;
int employeeID5 = newNextID(); //employeeID5 = 2;
return 0;
}
Statik yerel değişkenler ve statik küresel değişkenler için yukarıdaki kritere bakıldığında, aralarındaki farkın ne olabileceğini sormak cazip gelebilir. Global değişkenler kodun herhangi bir noktasında erişilebilir olsa da ( const -ness ve extern -ness'e bağlı olarak farklı çeviri biriminde olduğu gibi ), bir fonksiyon bloğu içinde tanımlanan statik bir değişkene doğrudan erişilemez. Değişkenin işlev değeri veya başvurusu ile döndürülmesi gerekir. Bunu bir örnekle gösterelim:
//localVarDemo2.cpp
//static storage duration with global scope
//note this variable can be accessed from outside the file
//in a different compilation unit by using `extern` specifier
//which might not be desirable for certain use case.
static int globalId = 0;
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()
{
//since globalId is accessible we use it directly
const int globalEmployee1Id = globalId++; //globalEmployeeId1 = 0;
const int globalEmployee2Id = globalId++; //globalEmployeeId1 = 1;
//const int employeeID1 = newID++; //this will lead to compilation error since newID++ is not accessible direcly.
int employeeID2 = newNextID(); //employeeID3 = 0;
int employeeID2 = newNextID(); //employeeID3 = 1;
return 0;
}
Statik global ve statik lokal değişken seçimi hakkında daha fazla açıklama bu yığın akışı iş parçacığında bulunabilir
(ii) adlandırılmamış bir yerel blok içindeki değişkenler için statik anahtar kelime.
yerel blok kapsam dışına çıktığında, yerel bir blok içindeki statik değişkenlere (fonksiyon bloğu değil) blok dışında erişilemez. Bu kurala dikkat edilmez.
//localVarDemo3.cpp
int main()
{
{
const static int static_local_scoped_variable {99};
}//static_local_scoped_variable goes out of scope
//the line below causes compilation error
//do_something is an arbitrary function
do_something(static_local_scoped_variable);
return 0;
}
C ++ 11 constexpr
, bir ifadenin derleme zamanında değerlendirilmesini garanti eden ve derleyicinin kodu optimize etmesine izin veren anahtar kelimeyi tanıttı . Şimdi, bir kapsam içindeki statik sabit değişkenin değeri derleme zamanında biliniyorsa, kod, şuna benzer bir şekilde optimize edilir constexpr
. İşte küçük bir örnek
Ben arasındaki farkı bakmak için de okuyucuları tavsiye constexpr
ve static const
değişkenler için bu stackoverflow iş parçacığı . bu, değişkenlere uygulanan statik anahtar kelimeye ilişkin açıklamamın sonucudur.
B. işlevler için kullanılan 'statik' anahtar kelime
işlevler açısından, statik anahtar kelimenin açık bir anlamı vardır. Burada, fonksiyonun bağlantısına atıfta bulunur.
Normalde, bir cpp dosyası içinde bildirilen tüm fonksiyonların varsayılan olarak harici bağlantısı vardır, yani bir dosyada tanımlanan bir fonksiyon, ileri bildirimle başka bir cpp dosyasında kullanılabilir.
işlev bildirimi bağlantısını dahili ile sınırlamadan önce statik bir anahtar kelime kullanmak , yani statik işlev tanımının dışındaki bir dosyada kullanılamaz.
C. Staitc Sınıfların üye değişkenleri ve işlevleri için kullanılan anahtar kelime
1. sınıfların üye değişkenleri için 'statik' anahtar kelime
Doğrudan burada bir örnekle başlıyorum
#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;
}
Bu örnekte, m_designNum statik değişkeni değerini korur ve bu tek özel üye değişken (statik olduğu için) DesignNumber nesne türünün tüm değişkenleri s / b ile paylaşılır
Ayrıca, diğer üye değişkenler gibi, bir sınıfın statik üye değişkenleri herhangi bir sınıf nesnesiyle ilişkilendirilmez; bu, ana işlevde herhangi birNumber öğesinin yazdırılmasıyla gösterilir
const ve const olmayan statik üye değişkenler
(i) sabit olmayan sınıf statik üye değişkenleri
Önceki örnekte, statik üyeler (hem genel hem de özel) sabit değildir. ISO standardı, sınıfta sabit olmayan statik üyelerin başlatılmasını yasaklar. Dolayısıyla, önceki örnekte olduğu gibi, sınıf tanımından sonra statik anahtar kelimenin atlanması gereken uyarı ile birlikte başlatılmaları gerekir.
(ii) sınıfının const-statik üye değişkenler
bu pürüzsüz olup, diğer sabit eleman değişken başlatma esası ile gider, bir sınıf, yani const statik üye değişkeni olabilir beyan noktasında başlatıldı ve sonunda başlatıldı edilebilir sınıf tanımlamasından sonra başlatılırken const anahtar sözcüğünün statik üyeye eklenmesi gerektiği konusunda bir uyarı.
Ancak, bildiri noktasında const statik üye değişkenleri başlatmanızı tavsiye ederim. Bu standart C ++ kuralına uygundur ve kodun daha temiz görünmesini sağlar
bir sınıftaki statik üye değişkenleri hakkında daha fazla örnek için learncpp.com adresinden aşağıdaki bağlantıya bakın
http://www.learncpp.com/cpp-tutorial/811-static-member-variables/
2. sınıfların üye işlevi için 'statik' anahtar kelime
Sınıfların üye değişkenleri gibi statik olabilir, sınıfların üye işlevleri de olabilir. Sınıfların normal üye işlevleri her zaman sınıf türündeki bir nesne ile ilişkilendirilir. Aksine, bir sınıfın statik üye işlevleri sınıfın herhangi bir nesnesiyle ilişkilendirilmez, yani * bu işaretçiye sahip değildir.
İkincisi, sınıfın statik üye işlevlerinde * hiçbir bu işaretçi olmadığından, bunlar ana işlevdeki (ClassName :: functionName ();) sınıf adı ve kapsam çözümleme işleci kullanılarak çağrılabilir.
Bir sınıfın üçüncü olarak statik üye işlevleri, bir sınıfın yalnızca statik üye değişkenlerine erişebilir, çünkü bir sınıfın statik olmayan üye değişkenleri bir sınıf nesnesine ait olmalıdır.
bir sınıftaki statik üye işlevleri hakkında daha fazla örnek için learncpp.com adresinden aşağıdaki bağlantıya bakın
http://www.learncpp.com/cpp-tutorial/812-static-member-functions/