Untuk mengklarifikasi pertanyaan, saya lebih suka mengkategorikan penggunaan kata kunci 'statis' dalam tiga bentuk berbeda:
(SEBUAH). variabel
(B). fungsi
(C). variabel anggota / fungsi kelas
Penjelasan berikut di bawah ini untuk masing-masing sub judul:
(A) kata kunci 'statis' untuk variabel
Yang satu ini bisa sedikit rumit tetapi jika dijelaskan dan dipahami dengan benar, itu cukup mudah.
Untuk menjelaskan hal ini, pertama-tama sangat berguna untuk mengetahui tentang ruang lingkup, durasi dan keterkaitan variabel, yang tanpanya hal-hal selalu sulit dilihat melalui konsep keruh dari kata kunci staic
1. Cakupan : Menentukan di mana dalam file, variabel dapat diakses. Ini dapat terdiri dari dua jenis: (i) Lingkup Lokal atau Blok . (ii) Lingkup Global
2. Durasi : Menentukan kapan variabel dibuat dan dihancurkan. Sekali lagi ini dari dua jenis: (i) Durasi Penyimpanan Otomatis (untuk variabel yang memiliki cakupan Blok atau Lokal). (ii) Durasi Penyimpanan Statis (untuk variabel yang memiliki Cakupan Global atau variabel lokal (dalam suatu fungsi atau dalam blok kode) dengan statis ).
3. Tautan : Menentukan apakah suatu variabel dapat diakses (atau ditautkan) di file lain. Sekali lagi (dan untungnya) terdiri dari dua jenis: (i) Tautan Internal
(untuk variabel yang memiliki Cakupan Blok dan Cakupan Global / Cakupan File / Cakupan Namespace Global) (ii) Tautan Eksternal (untuk variabel yang hanya memiliki Cakupan Global / Cakupan File / Ruang Lingkup Namespace Global)
Mari kita lihat contoh di bawah ini untuk pemahaman yang lebih baik tentang variabel global dan lokal polos (tidak ada variabel lokal dengan durasi penyimpanan statis):
//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
Kini hadir konsep Linkage. Ketika variabel global yang didefinisikan dalam satu file dimaksudkan untuk digunakan dalam file lain, keterkaitan variabel memainkan peran penting.
Tautan variabel global ditentukan oleh kata kunci: (i) statis , dan, (ii) eksternal
(Sekarang Anda mendapatkan penjelasannya)
kata kunci statis dapat diterapkan pada variabel dengan cakupan lokal dan global, dan dalam kedua kasus, keduanya memiliki arti yang berbeda. Pertama-tama saya akan menjelaskan penggunaan kata kunci 'statis' dalam variabel dengan cakupan global (di mana saya juga menjelaskan penggunaan kata kunci 'eksternal') dan kemudian untuk mereka yang memiliki cakupan lokal.
1. Kata Kunci Statis untuk variabel dengan cakupan global
Variabel global memiliki durasi statis, artinya mereka tidak keluar dari lingkup ketika blok kode tertentu (misalnya main ()) di mana ia digunakan berakhir. Bergantung pada tautan, mereka dapat diakses hanya di dalam file yang sama di mana mereka dideklarasikan (untuk variabel global statis), atau di luar file bahkan di luar file tempat mereka dideklarasikan (extern type global variable)
Dalam kasus variabel global yang memiliki extern specifier, dan jika variabel ini sedang diakses di luar file yang telah diinisialisasi, itu harus dideklarasikan ke depan dalam file di mana itu sedang digunakan, sama seperti fungsi harus maju menyatakan apakah definisi itu dalam file yang berbeda dari yang digunakan.
Sebaliknya, jika variabel global memiliki kata kunci statis, itu tidak dapat digunakan dalam file di luar yang telah dinyatakan.
(lihat contoh di bawah untuk klarifikasi)
misalnya:
//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;
}
sekarang setiap variabel dalam c ++ dapat berupa konst atau non-konst dan untuk setiap 'konstanta' kita mendapatkan dua case dari default c ++ linkage, jika tidak ada yang ditentukan:
(i) Jika variabel global adalah non-const, hubungannya dengan extern secara default , yaitu variabel global non-const dapat diakses dalam file .cpp lain dengan deklarasi maju menggunakan kata kunci extern (dengan kata lain, non const global variabel memiliki hubungan eksternal (dengan durasi statis tentu saja)). Juga penggunaan kata kunci extern dalam file asli di mana telah didefinisikan berlebihan. Dalam hal ini untuk membuat variabel global non-const tidak dapat diakses ke file eksternal, gunakan specifier 'statis' sebelum jenis variabel .
(ii) Jika variabel global adalah const, tautannya statis secara default , yaitu variabel global const tidak dapat diakses dalam file selain dari yang ditentukan, (dengan kata lain, variabel global const memiliki hubungan internal (dengan durasi statis tentu saja)). Juga penggunaan kata kunci statis untuk mencegah variabel global konst diakses dari file lain adalah berlebihan. Di sini, untuk membuat variabel global konst memiliki hubungan eksternal, gunakan specifier 'extern' sebelum jenis variabel
Berikut ini ringkasan untuk variabel lingkup global dengan berbagai tautan
//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
Selanjutnya kami menyelidiki bagaimana variabel global di atas berperilaku ketika diakses dalam file yang berbeda.
//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. Kata Kunci Statis untuk variabel dengan Lingkup Lokal
Pembaruan (Agustus 2019) pada kata kunci statis untuk variabel dalam cakupan lokal
Selanjutnya ini dapat dibagi lagi dalam dua kategori:
(i) kata kunci statis untuk variabel dalam blok fungsi , dan (ii) kata kunci statis untuk variabel dalam blok lokal yang tidak disebutkan namanya.
(i) kata kunci statis untuk variabel dalam blok fungsi.
Sebelumnya, saya menyebutkan bahwa variabel dengan cakupan lokal memiliki durasi otomatis, yaitu mereka muncul ketika blok dimasukkan (baik itu blok normal, baik itu blok fungsi) dan tidak ada lagi ketika blok berakhir, panjang cerita pendek, variabel dengan cakupan lokal memiliki durasi otomatis dan variabel durasi otomatis (dan objek) tidak memiliki hubungan yang berarti mereka tidak terlihat di luar blok kode.
Jika specifier statis diterapkan ke variabel lokal dalam blok fungsi, ia mengubah durasi variabel dari otomatis ke statis dan waktu hidup adalah seluruh durasi program yang berarti memiliki lokasi memori tetap dan nilainya diinisialisasi hanya sekali sebelum memulai program seperti yang disebutkan dalam referensi cpp (inisialisasi tidak boleh dikacaukan dengan penugasan)
mari kita lihat sebuah contoh.
//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;
}
Melihat kriteria di atas untuk variabel lokal statis dan variabel global statis, orang mungkin tergoda untuk bertanya, apa perbedaan di antara mereka. Sementara variabel global dapat diakses pada setiap titik di dalam kode (di sama serta unit terjemahan yang berbeda tergantung pada const -ness dan ekstern -ness), variabel statis didefinisikan dalam blok fungsi tidak langsung dapat diakses. Variabel harus dikembalikan oleh nilai fungsi atau referensi. Mari kita tunjukkan ini dengan sebuah contoh:
//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;
}
Penjelasan lebih lanjut tentang pilihan variabel lokal global dan statis statis dapat ditemukan di untaian stackoverflow ini
(ii) kata kunci statis untuk variabel dalam blok lokal yang tidak disebutkan namanya.
variabel statis dalam blok lokal (bukan blok fungsi) tidak dapat diakses di luar blok setelah blok lokal keluar dari ruang lingkup. Tidak ada peringatan untuk aturan ini.
//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 memperkenalkan kata kunci constexpr
yang menjamin evaluasi ekspresi pada waktu kompilasi dan memungkinkan kompiler untuk mengoptimalkan kode. Sekarang jika nilai variabel const statis dalam lingkup diketahui pada waktu kompilasi, kode dioptimalkan dengan cara yang mirip dengan yang ada constexpr
. Ini contoh kecil
Saya merekomendasikan pembaca juga untuk mencari perbedaan antara constexpr
dan static const
untuk variabel-variabel di thread stackoverflow ini . ini menyimpulkan penjelasan saya untuk kata kunci statis yang diterapkan pada variabel.
B. kata kunci 'statis' yang digunakan untuk fungsi
dalam hal fungsi, kata kunci statis memiliki makna langsung. Di sini, ini merujuk pada keterkaitan fungsi
Biasanya semua fungsi yang dideklarasikan dalam file cpp memiliki hubungan eksternal secara default, yaitu fungsi yang didefinisikan dalam satu file dapat digunakan dalam file cpp lain dengan deklarasi maju.
menggunakan kata kunci statis sebelum deklarasi fungsi membatasi keterkaitannya dengan internal , yaitu fungsi statis tidak dapat digunakan dalam file di luar definisi.
C. Staitc Keyword yang digunakan untuk variabel anggota dan fungsi kelas
1. kata kunci 'statis' untuk variabel anggota kelas
Saya mulai langsung dengan contoh di sini
#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;
}
Dalam contoh ini, variabel statis m_designNum mempertahankan nilainya dan variabel anggota pribadi tunggal ini (karena statis) dibagikan dengan semua variabel tipe objek DesignNumber
Juga seperti variabel anggota lainnya, variabel anggota statis suatu kelas tidak terkait dengan objek kelas apa pun, yang ditunjukkan oleh pencetakan anyNumber di fungsi utama
variabel anggota statis vs non-const di kelas
(i) variabel anggota statis kelas non-const
Dalam contoh sebelumnya anggota statis (baik publik dan pribadi) adalah konstanta non. Standar ISO melarang anggota statis non-const untuk diinisialisasi di kelas. Karenanya seperti pada contoh sebelumnya, mereka harus diinisialisasi setelah definisi kelas, dengan peringatan bahwa kata kunci statis perlu dihilangkan.
(ii) variabel anggota const-statis kelas
ini mudah dan berjalan dengan konvensi inisialisasi variabel anggota konst, yaitu variabel anggota const statis kelas dapat diinisialisasi pada titik deklarasi dan mereka dapat diinisialisasi pada akhir deklarasi kelas dengan satu peringatan bahwa kata kunci const perlu ditambahkan ke anggota statis ketika diinisialisasi setelah definisi kelas.
Namun saya akan merekomendasikan untuk menginisialisasi variabel anggota const statis pada titik deklarasi. Ini berlaku dengan konvensi C ++ standar dan membuat kode terlihat lebih bersih
untuk lebih banyak contoh tentang variabel anggota statis di kelas, lihat tautan berikut dari learncpp.com
http://www.learncpp.com/cpp-tutorial/811-static-member-variables/
2. kata kunci 'statis' untuk fungsi anggota kelas
Sama seperti variabel anggota kelas dapat, bersifat statis, demikian juga fungsi anggota kelas. Fungsi anggota normal dari kelas selalu dikaitkan dengan objek dari tipe kelas. Sebaliknya, fungsi anggota statis suatu kelas tidak terkait dengan objek kelas apa pun, yaitu mereka tidak memiliki * penunjuk ini.
Kedua karena fungsi anggota statis dari kelas tidak memiliki * penunjuk ini, mereka dapat dipanggil menggunakan nama kelas dan operator resolusi lingkup dalam fungsi utama (ClassName :: functionName ();)
Ketiga, fungsi anggota statis suatu kelas hanya dapat mengakses variabel anggota statis suatu kelas, karena variabel anggota non-statis suatu kelas harus dimiliki oleh objek kelas.
untuk lebih banyak contoh tentang fungsi anggota statis di kelas, lihat tautan berikut dari learncpp.com
http://www.learncpp.com/cpp-tutorial/812-static-member-functions/