Kas yra „statinė“ funkcija?

Klausimas buvo apie paprastą c funkciją, o ne static metodą, kaip paaiškinta komentaruose.

Na, aš suprantu, kas yra static kintamasis, bet kas yra static funkcija?

Ir kodėl taip, kad jei paskelbsiu funkciją, tarkim void print_matrix , leiskite jam pasakyti ac ( void print_matrix ah ) ir įtraukti "ac" - aš gausiu "print_matrix@@....) already defined in a.obj" , BET, jei aš Aš ją paskelbiu kaip static void print_matrix , tada ji yra sudaryta?

UPDATE Tiesiog paaiškinti situaciją - žinau, kad .c įtraukimas yra blogas, kaip daugelis jūsų nurodė. Aš tiesiog tai padarysiu, kad laikinai atlaisvintume pagrindinės srities erdvę, kol turėsiu geriau suprasti, kaip suskirstyti visas šias funkcijas į teisingus .h ir .c failus. Tiesiog laikinas, greitas sprendimas.

431
17 февр. Slava V - 17 vasaris. 2009-02-17 21:26 '09 9:26 pm 2009-02-17 21:26
@ 11 atsakymų

static funkcijos yra funkcijos, kurios matomos tik kitoms to paties failo funkcijoms (tiksliau tas pats vertimo vienetas ).

EDIT . Tiems, kurie manė, kad klausimų autorius reiškė „klasės metodą“: kadangi klausimas pažymėtas C , tai reiškia įprastą senąją C funkciją. Klasės metodams (C ++ / Java / ...) static reiškia, kad šis metodas gali būti vadinamas pati klasė, šios klasės nėra.

595
17 февр. Johannes Weiss atsakymas, pateiktas vasario 17 d. 2009-02-17 21:27 '09 9:27 pm 2009-02-17 21:27

Yra didelis skirtumas tarp statinių C funkcijų ir statinių narių funkcijų C + +. C atveju statinė funkcija nėra matoma už jo vertimo vieneto, kuris yra objekto failas, į kurį jis yra sudarytas. Kitaip tariant, statinė funkcijos funkcija riboja jos taikymo sritį. * .C faile galite manyti, kad statinė funkcija yra „privati“ (nors tai nėra visiškai teisinga).

C ++ „statinis“ taip pat gali būti taikomas šių klasių funkcijų nariams ir nariams. Statinis duomenų elementas taip pat vadinamas „klasės kintamuoju“, o ne statinis duomenų elementas yra „instancijos kintamasis“. Tai yra Smalltalk terminologija. Tai reiškia, kad yra tik viena statinio duomenų elemento kopija, kurią dalijasi visi klasės objektai, o kiekvienas objektas turi savo nestatinio duomenų elemento kopiją. Taigi statinis duomenų narys iš esmės yra pasaulinis kintamasis, kuris yra klasės narys.

Ne statinės narių funkcijos gali būti susijusios su visais klasės duomenų nariais: statiniu ir nestatiniu. Statinės narių funkcijos gali veikti tik su statiniais duomenų elementais.

Vienas iš būdų manyti, kad C + + statiniuose duomenų elementuose ir statinėse narių funkcijose nėra jokio objekto, bet visai klasei.

180
17 февр. Atsakymas pateikiamas Dima 17 vasario mėn. 2009-02-17 21:44 '09 at 9:44 PM 2009-02-17 21:44

Yra dvi galimybės naudoti statinį raktinį žodį, kai kalbama apie funkcijas „C ++“.

Pirma, norint pažymėti funkciją kaip vidinį ryšį, jis negali būti nurodomas kituose vertimo padaliniuose. Šis naudojimas yra netinkamas C ++. Šiam naudojimui yra naudingesnės vardų vietos.

 // inside some .cpp file: static void foo(); // old "C" way of having internal linkage // C++ way: namespace { void this_function_has_internal_linkage() { // ... } } 

Antrasis panaudojimas reiškia klasę. Jei klasė turi statinę nario funkciją, tai reiškia, kad funkcija yra klasės narė (ir turi įprastą prieigą prie kitų narių), tačiau negali būti iškviesta per konkretų objektą. Kitaip tariant, šios funkcijos viduje nėra „šio“ rodiklio.

72
17 февр. Atsakymą pateikė Brian Neal , vasario 17 d. 2009-02-17 21:47 '09 at 9:47 PM 2009-02-17 21:47

Minimalaus daugiafunkcinio ploto pavyzdys

Čia aš parodysiu, kaip static paveikia funkcijų apibrėžimų apimtis keliuose failuose.

kintamosios srovės

 #include <stdio.h>void f(void);  static void sf() { puts("a sf"); } void a() { f(); sf(); } 

main.c

 #include <stdio.h> void a(void); void f() { puts("main f"); } static void sf() { puts("main sf"); } void m() { f(); sf(); } int main() { m(); a(); return 0; } 

GitHub aukštyn .

Sudaryti ir paleisti:

 gcc -c ac -o ao gcc -c main.c -o main.o gcc -o main main.o ao ./main 

Išeiti:

 main f main sf main f a sf 

aiškinimas

  • Yra dvi atskiros sf funkcijos, po vieną kiekvienam failui.
  • yra viena bendra funkcija f

Kaip įprasta, tuo mažesnė taikymo sritis, tuo geriau, jei visada galite deklaruoti static funkcijas.

C programoje failai dažnai naudojami atstovauti „klasėms“, o static funkcijos - „privatūs“ klasės metodai.

Įprastas „C“ šablonas yra perduoti this struktūrą kaip pirmąjį „metodo“ argumentą, kuris iš esmės daro tai, ką C + + atlieka po gaubtu.

Kokie standartai apie tai sako

C99 N1256 Projektas 6.7.1 „Saugojimo klasės specifikatoriai“ teigia, kad static yra „saugojimo klasės specifikatorius“.

6.2.2 / 3 „Tapatybės nuorodos“ sako, kad static reiškia internal linkage :

Jei objekto ar funkcijos failo srities identifikatoriaus deklaracijoje yra statinio saugojimo klasės specifikatorius, identifikatorius yra vidaus ryšys.

ir 6.2.2 / 2 sako, kad internal linkage elgiasi taip, kaip mūsų pavyzdyje:

Vertimo vienetų ir bibliotekų, sudarančių visą programą, rinkinyje kiekviena konkretaus identifikatoriaus deklaracija su išorine nuoroda žymi tą patį objektą ar funkciją. Tame pačiame vertimo vienete kiekviena identifikatoriaus deklaracija su vidine nuoroda reiškia tą patį objektą arba funkciją.

kur „vertimo vienetas“ yra pirminis failas po paruošimo.

Kaip GCC tai įgyvendina ELF (Linux)?

Su STB_LOCAL privaloma.

Jei rengiame:

 int f() { return 0; } static int sf() { return 0; } 

ir analizuokite simbolių lentelę su:

 readelf -s main.o 

išvestyje yra:

 Num: Value Size Type Bind Vis Ndx Name 5: 000000000000000b 11 FUNC LOCAL DEFAULT 1 sf 9: 0000000000000000 11 FUNC GLOBAL DEFAULT 1 f 

taigi, privalomumas yra vienintelis reikšmingas skirtumas tarp jų. Value yra tik jų kompensacija .bss skiltyje, todėl tikimės, kad ji bus kitokia.

STB_LOCAL dokumentuotas ELF specifikacijoje šiuo adresu : http://www.sco.com/developers/gabi/2003-12-17/ch4.symtab.html :

STB_LOCAL Vietiniai simboliai nėra matomi už objekto failo, kuriame yra jų apibrėžimas. Vietiniai to paties pavadinimo simboliai gali egzistuoti keliose rinkmenose nesikišdami vienas į kitą.

todėl jis idealiai tinka static .

Funkcijos be statikos yra STB_GLOBAL , o specifikacijoje nurodyta:

Kai nuorodų redaktorius sujungia kelis perkeliamus objekto failus, jis neleidžia keleto STB_GLOBAL simbolių apibrėžimų, turinčių tą patį pavadinimą.

kuris atitinka keletą netarčių apibrėžčių klaidų.

Jei -O3 optimizuojame -O3 , sf simbolis visiškai pašalinamas iš simbolių lentelės: jis negali būti naudojamas išorėje. TODO kodėl stacionarias funkcijas laikau simbolių lentelėje, kai nėra optimizavimo? Ar jie gali būti naudojami nieko?

Taip pat žr

C ++ anoniminės vardų vietos

„C ++“ galite naudoti anonimines vardų vietas vietoj statinių, kurios suteikia panašų efektą, bet papildomai slepia tipo apibrėžimus: Nenurodytos / anoniminės vardų erdvės nuo statinių funkcijų

40
19 мая '15 в 10:56 2015-05-19 10:56 atsakė Ciro Santilli 改造 改造 中心 六四 事件 法轮功 Gegužės 19, 15, 10:56 2015-05-19 10:56

Toliau pateikiamos paprastos C funkcijos - „C ++“ klasėje „statinis“ modifikatorius turi skirtingą reikšmę.

Jei turite tik vieną failą, šis modifikatorius neturi jokios reikšmės. Skirtumas yra dideliuose projektuose su keliais failais:

„C“ kiekvienas „modulis“ (pavyzdys.c ir sample.h derinys) yra sukompiliuotas atskirai, o po to kiekvienas sukomponuotas objekto failas (sample.o) yra susietas su vykdomuoju nuorodikliu.

Tarkime, jūs turite keletą failų, kuriuos įtraukėte į pagrindinį failą, o du iš jų turi funkciją, kuri naudojama tik patogumui, kurį vadina add(int a, b) - kompiliatorius lengvai sukurs šių dviejų modulių objektų failus, tačiau ryšys sukels klaidą, nes jis suranda dvi funkcijas, turinčias tą patį pavadinimą, ir nežino, kuris iš jų turėtų būti naudojamas (net jei nėra jokios nuorodos, nes jos nenaudojamos kitur, bet savo rinkmenoje).

Štai kodėl šią funkciją, kuri naudojama tik viduje, atliekate statine funkcija. Tokiu atveju kompiliatorius nesukuria tipiškos nuorodos „jūs galite susieti šį dalyką“, - susieti su nuoroda, todėl sąsaja nemato šios funkcijos ir nesukels klaidos.

18
26 апр. atsakymas dersimn 26 Bal 2013-04-26 01:49 '13 ne 1:49 2013-04-26 01:49

Pirma, paprastai bloga idėja įtraukti .cpp failą į kitą failą - tai sukelia tokių problemų :-) Įprastas būdas yra sukurti atskirus kompiliavimo modulius ir pridėti pridėtos rinkmenos antraštės failą.

Antra:

C ++ čia yra šiek tiek paini terminologija - apie tai nežinojau, kol ji nebuvo nurodyta komentaruose.

a) static functions paveldėtos iš C, ir apie ką kalbate čia. Už bet kurios klasės. Statinė funkcija reiškia, kad ji nėra matoma už dabartinio kompiliavimo modulio, taigi jūsų atveju a.obj turi kopiją, o kitas jūsų kodas turi nepriklausomą kopiją. (Galutinio įvykio plyšimas su keliomis kodo kopijomis).

b) static member function - kokia objekto orientacija vadina statinį metodą . Gyvena klasėje. Jūs jį vadinate klasėje, o ne per objekto pavyzdį.

Šios dvi skirtingos statinių funkcijų apibrėžtys yra visiškai skirtingos. Būkite atsargūs - bus drakonai.

15
17 февр. Atsakymą pateikė Douglas Leeder , vasario 17 d. 2009-02-17 21:40 '09 21:40 2009-02-17 21:40

statinės funkcijos apibrėžia šį simbolį kaip vidinį. Taigi, jis nebus matomas ryšiui iš išorės, bet tik su viena kompiliacijos vieneto funkcijomis, paprastai tame pačiame faile.

14
17 февр. atsakymas pateikiamas raimue 17 vas . 2009-02-17 21:28 '09, 21:28 2009-02-17 21:28

Statinė funkcija yra funkcija, kurią gali priskirti pati klasė, o ne klasės klasė.

Pavyzdžiui, ne statinis:

 Person* tom = new Person(); tom->setName("Tom"); 

Šis metodas veikia klasės klasėje, o ne pačioje klasėje. Tačiau galite turėti statinį metodą, kuris gali veikti be pavyzdžio. Kartais tai naudojama gamykloje:

 Person* tom = Person::createNewPerson(); 
8
17 февр. atsakymą pateikė „ Papūgos “ vasario 17 d. 2009-02-17 21:28 '09, 21:28 2009-02-17 21:28

Atsakymas į statinę funkciją priklauso nuo kalbos:

1) Kalbose, kuriose nėra OOPS, pvz., C, tai reiškia, kad funkcija yra tik faile, kur jis yra apibrėžtas.

2) Kalbose su OOPS, pvz., C ++, tai reiškia, kad funkcija gali būti vadinama tiesiogiai klasėje nesukuriant egzemplioriaus.

7
06 марта '16 в 16:31 2016-03-06 16:31 atsakymą pateikė vartotojo2410022 kovo 06 d. 16:31 2016-03-06 16:31

Minus nit: vertimo vienetui matomos statinės funkcijos, kurios daugeliu praktinių atvejų yra failas, kuriame apibrėžta funkcija. Gauta klaida paprastai vadinama „Vieno apibrėžimo“ taisyklės pažeidimu.

Standartas tikriausiai sako kažką panašaus:

"Kiekvienoje programoje turi būti tiksliai apibrėžta kiekviena šioje programoje naudojama ne native funkcija arba objektas, nereikalaujama jokios diagnostikos."

Tai būdas pažvelgti į statines funkcijas. Tačiau tai yra pasenusi C ++.

Be to, „C ++“ galite deklaruoti statines nario funkcijas. Tai daugiausia metafunkcijos, t.y. Jie neaprašo / nekeičia konkretaus objekto elgesio / būklės, bet veikia visai klasei. Be to, tai reiškia, kad jums nereikia sukurti objekto, kuris vadintų statinę nario funkciją. Be to, tai taip pat reiškia, kad iš tokios funkcijos naudojate statinius nario kintamuosius.

Norėčiau pridėti, pavyzdžiui, „Parrot Singleton“ modelį, pagrįstą tokia statine nario funkcija, kad gautumėte / panaudotumėte vieną objektą per visą programos gyvavimo ciklą.

6
17 февр. atsakymas pateikiamas dirggatiškai 17 vasaris. 2009-02-17 21:50 '09 9:50 val. 2009-02-17 21:50

kompiliatoriaus statinei funkcijai „c“ nesukurs savo vidinių kintamųjų krūvoje, todėl statinės funkcijos skambutis yra greitesnis, todėl negalite naudoti iniciatorių, tokių kaip: char c = 'A'.

-4
05 нояб. atsakymas pateikiamas Alex 05 lapkričio. 2016-11-05 22:17 '16 at 10:17 pm 2016-11-05 22:17

Kiti klausimai apie žymes arba „ Užduoti klausimą“