Pertanyaannya tentang polos c fungsi, bukan c ++ static
metode, seperti yang dijelaskan dalam komentar.
Saya mengerti apa static
variabel itu, tapi apa static
fungsinya?
Dan mengapa jika saya mendeklarasikan suatu fungsi, katakanlah void print_matrix
, dalam katakanlah a.c
(TANPA a.h
) dan sertakan "a.c"
- Saya mengerti "print_matrix@@....) already defined in a.obj"
, TETAPI jika saya mendeklarasikan fungsinya static void print_matrix
saat kompilasi?
PEMBARUAN Hanya untuk menjernihkan - saya tahu bahwa termasuk .c
itu buruk, seperti yang banyak dari Anda tunjukkan. Saya hanya melakukannya untuk membersihkan ruang sementara main.c
sampai saya memiliki ide yang lebih baik tentang bagaimana mengelompokkan semua fungsi tersebut ke dalam file .h
dan .c
file yang benar. Hanya solusi sementara dan cepat.
sumber
Ada perbedaan besar antara fungsi statis di C dan fungsi anggota statis di C ++. Dalam C, fungsi statis tidak terlihat di luar unit terjemahannya, yang merupakan file objek yang dikompilasi. Dengan kata lain, membuat fungsi statis membatasi ruang lingkupnya. Anda dapat menganggap fungsi statis sebagai "pribadi" untuk file * .c-nya (walaupun itu tidak sepenuhnya benar).
Dalam C ++, "statis" juga dapat berlaku untuk fungsi anggota dan data anggota kelas. Anggota data statis juga disebut "variabel kelas", sedangkan anggota data non-statis adalah "variabel instan". Ini adalah terminologi Smalltalk. Ini berarti bahwa hanya ada satu salinan anggota data statis yang dibagikan oleh semua objek kelas, sementara setiap objek memiliki salinan sendiri anggota data non-statis. Jadi anggota data statis pada dasarnya adalah variabel global, yaitu anggota kelas.
Fungsi anggota non-statis dapat mengakses semua data anggota kelas: statis dan non-statis. Fungsi anggota statis hanya dapat beroperasi pada anggota data statis.
Salah satu cara untuk memikirkan hal ini adalah bahwa dalam C ++ anggota data statis dan fungsi anggota statis bukan milik objek apa pun, tetapi untuk seluruh kelas.
sumber
Ada dua kegunaan untuk kata kunci statis ketika datang ke fungsi di C ++.
Yang pertama adalah untuk menandai fungsi sebagai memiliki hubungan internal sehingga tidak dapat direferensikan dalam unit terjemahan lainnya. Penggunaan ini tidak digunakan lagi dalam C ++. Ruang nama yang tidak disebutkan namanya lebih disukai untuk penggunaan ini.
Penggunaan kedua adalah dalam konteks kelas. Jika kelas memiliki fungsi anggota statis, itu berarti fungsi tersebut adalah anggota kelas (dan memiliki akses biasa ke anggota lain), tetapi tidak perlu dipanggil melalui objek tertentu. Dengan kata lain, di dalam fungsi itu, tidak ada pointer "ini".
sumber
Contoh lingkup multi-file runnable minimal
Di sini saya menggambarkan bagaimana
static
memengaruhi ruang lingkup definisi fungsi di beberapa file.ac
main.c
GitHub hulu .
Kompilasi dan jalankan:
Keluaran:
Penafsiran
sf
, satu untuk setiap filef
Seperti biasa, semakin kecil cakupannya, semakin baik, jadi selalu nyatakan fungsi
static
jika Anda bisa.Dalam pemrograman C, file sering digunakan untuk mewakili "kelas", dan
static
fungsi mewakili metode "pribadi" kelas.Pola C yang umum adalah meneruskan
this
struct sekitar sebagai argumen "metode" pertama, yang pada dasarnya adalah apa yang dilakukan C ++ di bawah tenda.Apa standar katakan tentang itu
C99 N1256 konsep 6.7.1 " Penentu kelas penyimpanan" mengatakan bahwa itu
static
adalah " penentu kelas penyimpanan".6.2.2 / 3 "Tautan pengidentifikasi" kata
static
menyiratkaninternal linkage
:dan 6.2.2 / 2 mengatakan bahwa
internal linkage
berperilaku seperti pada contoh kita:di mana "unit terjemahan" adalah file sumber setelah preprocessing.
Bagaimana GCC mengimplementasikannya untuk ELF (Linux)?
Dengan
STB_LOCAL
mengikat.Jika kami kompilasi:
dan bongkar tabel simbol dengan:
output berisi:
jadi pengikatan adalah satu-satunya perbedaan yang signifikan di antara mereka.
Value
hanya offset mereka ke dalam.bss
bagian, jadi kami perkirakan berbeda.STB_LOCAL
didokumentasikan pada spesifikasi ELF di http://www.sco.com/developers/gabi/2003-12-17/ch4.symtab.html :yang membuatnya menjadi pilihan yang tepat untuk diwakili
static
.Fungsi tanpa statis adalah
STB_GLOBAL
, dan spesifikasi mengatakan:yang koheren dengan kesalahan tautan pada beberapa definisi non statis.
Jika kita menghidupkan optimasi dengan
-O3
,sf
simbol dihapus seluruhnya dari tabel simbol: itu tidak dapat digunakan dari luar. TODO mengapa menyimpan fungsi statis pada tabel simbol sama sekali ketika tidak ada optimasi? Bisakah mereka digunakan untuk apa saja?Lihat juga
extern
adalah kebalikan daristatic
, dan fungsi sudahextern
secara default: Bagaimana cara saya menggunakan extern untuk berbagi variabel antara file sumber?C ++ ruang nama anonim
Dalam C ++, Anda mungkin ingin menggunakan ruang nama anonim alih-alih statis, yang mencapai efek yang serupa, tetapi lebih lanjut menyembunyikan definisi tipe: Ruang nama tidak bernama / anonim vs. fungsi statis
sumber
void f() { puts("sf"); }
(yaitu dua definisif()
) menyebabkan perilaku yang tidak terdefinisi tanpa diagnostik yang diperlukan. Ini masalah kualitas tautan untuk benar-benar melihat pesan kesalahan.Berikut ini adalah tentang fungsi C biasa - dalam kelas C ++ pengubah 'statis' memiliki arti lain.
Jika Anda hanya memiliki satu file, pengubah ini sama sekali tidak membuat perbedaan. Perbedaannya muncul pada proyek yang lebih besar dengan banyak file:
Dalam C, setiap "modul" (kombinasi dari sample.c dan sample.h) dikompilasi secara independen dan setelah itu setiap file objek yang dikompilasi (sample.o) dihubungkan bersama-sama ke file yang dapat dieksekusi oleh linker.
Katakanlah Anda memiliki beberapa file yang Anda sertakan dalam file utama Anda dan dua di antaranya memiliki fungsi yang hanya digunakan secara internal untuk kenyamanan yang disebut
add(int a, b)
- kompiler akan dengan mudah membuat file objek untuk dua modul tersebut, tetapi linker akan melakukan kesalahan, karena ia menemukan dua fungsi dengan nama yang sama dan tidak tahu mana yang harus digunakan (bahkan jika tidak ada yang ditautkan, karena mereka tidak digunakan di tempat lain tetapi dalam file itu sendiri).Inilah sebabnya mengapa Anda membuat fungsi ini, yang hanya digunakan internal, fungsi statis. Dalam hal ini kompiler tidak membuat tipikal "Anda dapat menautkan hal ini" -flag untuk tautan, sehingga tautan tersebut tidak melihat fungsi ini dan tidak akan menghasilkan kesalahan.
sumber
Pertama: Ini umumnya ide yang buruk untuk memasukkan
.cpp
file ke file lain - itu mengarah ke masalah seperti ini :-) Cara normal adalah membuat unit kompilasi terpisah, dan menambahkan file header untuk file yang disertakan.Kedua:
C ++ memiliki beberapa terminologi yang membingungkan di sini - saya tidak tahu tentangnya sampai ditunjukkan dalam komentar.
a)
static functions
- diwarisi dari C, dan apa yang Anda bicarakan di sini. Di luar kelas apa pun. Fungsi statis berarti tidak terlihat di luar unit kompilasi saat ini - jadi dalam kasus Anda a.obj memiliki salinan dan kode Anda yang lain memiliki salinan independen. (Kembung executable terakhir dengan banyak salinan kode).b)
static member function
- istilah Orientasi Objek apa yang disebut metode statis . Tinggal di dalam kelas. Anda menyebutnya dengan kelas daripada melalui instance objek.Dua definisi fungsi statis yang berbeda ini sama sekali berbeda. Hati-hati - ini naga.
sumber
definisi fungsi statis akan menandai simbol ini sebagai internal. Jadi itu tidak akan terlihat untuk menghubungkan dari luar, tetapi hanya untuk fungsi-fungsi dalam unit kompilasi yang sama, biasanya file yang sama
sumber
Fungsi statis adalah fungsi yang dapat dipanggil pada kelas itu sendiri, sebagai lawan dari instance kelas.
Misalnya non-statis adalah:
Metode ini berfungsi pada instance kelas, bukan kelas itu sendiri. Namun Anda dapat memiliki metode statis yang dapat bekerja tanpa harus memiliki instance. Ini kadang-kadang digunakan dalam pola Pabrik:
sumber
Minor nit: fungsi statis dapat dilihat oleh unit terjemahan, yang untuk sebagian besar kasus praktis adalah fungsi file tersebut. Kesalahan yang Anda peroleh biasanya disebut sebagai pelanggaran Aturan Satu Definisi.
Standar mungkin mengatakan sesuatu seperti:
Itu adalah cara C memandang fungsi statis. Namun ini sudah usang dalam C ++.
Di C ++, selain itu, Anda dapat mendeklarasikan fungsi anggota statis. Ini sebagian besar adalah metafungsi yaitu mereka tidak menggambarkan / memodifikasi perilaku objek / negara tetapi bertindak pada seluruh kelas itu sendiri. Juga, ini berarti bahwa Anda tidak perlu membuat objek untuk memanggil fungsi anggota statis. Selanjutnya, ini juga berarti, Anda hanya mendapatkan akses ke variabel anggota statis dari dalam fungsi tersebut.
Saya akan menambahkan contoh Parrot pola Singleton yang didasarkan pada semacam ini fungsi anggota statis untuk mendapatkan / menggunakan objek tunggal sepanjang masa program.
sumber
Jawaban untuk fungsi statis tergantung pada bahasa:
1) Dalam bahasa tanpa OOPS seperti C, itu berarti bahwa fungsi tersebut hanya dapat diakses dalam file yang ditentukan.
2) Dalam bahasa dengan OOPS seperti C ++, itu berarti bahwa fungsi tersebut dapat dipanggil langsung di kelas tanpa membuat turunannya.
sumber
static
memiliki cakupan file juga, seperti di C.Karena fungsi statis hanya terlihat di file ini. Sebenarnya, kompiler dapat melakukan beberapa optimasi untuk Anda jika Anda menyatakan "statis" untuk beberapa fungsi.
Ini adalah contoh sederhana.
main.c
Dan kompilasi dengan
Anda akan melihatnya gagal. Karena Anda bahkan tidak mengimplementasikan fungsi ghost ().
Tetapi bagaimana jika kita menggunakan perintah berikut.
Ini berhasil , dan program ini dapat dijalankan secara normal.
Mengapa? Ada 3 poin kunci.
Hanya jika 3 kondisi ini semuanya benar, Anda dapat melewati kompilasi. Karena deklarasi "statis" ini, kompiler dapat mengonfirmasi bahwa test () tidak akan pernah dipanggil di file lain. Kompiler Anda dapat menghapus test () saat kompilasi. Karena kita tidak memerlukan test (), tidak masalah apakah ghost () didefinisikan atau diimplementasikan.
sumber
Mari kita mulai dari awal.
Semuanya didasarkan pada hal yang disebut "tautan":
Jika suatu fungsi didefinisikan tanpa specifier kelas penyimpanan, fungsi tersebut memiliki
extern
tautan secara default:Itu berarti bahwa - jika program Anda berisi beberapa unit terjemahan / file sumber (
.c
atau.cpp
) - fungsinya terlihat di semua unit terjemahan / file sumber yang dimiliki program Anda.Ini bisa menjadi masalah dalam beberapa kasus. Bagaimana jika Anda ingin menggunakan dua fungsi yang berbeda (definisi), tetapi dengan nama fungsi yang sama dalam dua konteks yang berbeda (sebenarnya konteks file).
Dalam C dan C ++,
static
kualifikasi kelas penyimpanan yang diterapkan ke fungsi pada lingkup file (bukan fungsi anggota statis kelas di C ++ atau fungsi dalam blok lain) sekarang hadir untuk membantu dan menandakan bahwa fungsi masing-masing hanya terlihat di dalam unit terjemahan / file sumber yang didefinisikan dan bukan dalam TLU / file lainnya.Dengan demikian,
static
fungsi A hanya masuk akal, jika:Program Anda berisi beberapa unit terjemahan / file sumber (
.c
atau.cpp
).dan
Anda ingin membatasi ruang lingkup fungsi ke file, di mana fungsi spesifik didefinisikan.
Jika tidak kedua persyaratan ini cocok, Anda tidak perlu membahas tentang kualifikasi fungsi sebagai
static
.Catatan Samping:
Seperti yang telah disebutkan,
static
fungsi A sama sekali tidak ada perbedaan sama sekali antara C dan C ++, karena ini adalah fitur C ++ yang diwarisi dari C.Tidak masalah bahwa di komunitas C ++, ada debat yang memilukan tentang depresiasi fungsi kualifikasi karena
static
dibandingkan dengan penggunaan ruang nama yang tidak disebutkan namanya , mula-mula diinisialisasi dengan paragraf yang salah tempat dalam standar C ++ 03, menyatakan penggunaan fungsi statis seperti yang sudah usang yang segera direvisi oleh komite itu sendiri dan dihapus di C ++ 11.Ini tunduk pada berbagai pertanyaan SO:
Ruang nama tanpa nama / anonim vs. fungsi statis
Keunggulan namespace tanpa nama dibandingkan statis?
Mengapa namespace tanpa nama adalah alternatif "superior" dari statis?
Penghentian kata kunci statis ... tidak lagi?
Faktanya, ini belum usang per standar C ++. Dengan demikian, penggunaan
static
fungsi masih sah. Bahkan jika ruang nama yang tidak disebutkan namanya memiliki keuntungan, diskusi tentang menggunakan atau tidak menggunakan fungsi statis di C ++ tunduk pada satu pikiran (berdasarkan pendapat) dan dengan yang tidak cocok untuk situs web ini.sumber