Raport - cu funcția - informatică, programare

Ca de obicei mod de a face ceva în programul C ++ - este de a apela o funcție care face acest lucru. O definiție funcție este o modalitate de a întreba cum ar trebui să facă unele acțiuni. Funcția nu poate fi invocată atâta timp cât nu este descrisă.







Descrierea funcției specifică numele funcției, tipul valorii funcției de întoarcere (dacă este cazul) și numărul și tipurile de parametri care trebuie să fie într-un apel de funcție.

sqrt dublu extern (dublu);

elem * next_elem extern ();

char * strcpy extern (char * la, const char * de la);

exit void extern (int);

Semantica parametri de transmisie semantică identică de inițializare. Tipuri de parametri sunt verificate, iar atunci când este necesar a făcut o conversie de tip implicită. De exemplu, în cazul în care s-au dat definițiile anterioare,

double SR2 = sqrt (2);

ar referi în mod corespunzător la funcția sqrt () cu valoarea floating punctul 2.0. Valoarea unui astfel de verificare tip și de tipul de conversie este enormă.

Funcția Descrierea poate conține numele parametrilor. Acest lucru poate ajuta cititorul, dar compilatorul ignoră pur și simplu aceste nume.

Fiecare funcție care este numit în program trebuie să fie definit undeva (o singură dată). Definiție funcție - această descriere a funcției, care determină organismul să funcționeze.

void swap pe extern (int *, int *); // descriere

void swap (int *, int *) // definiție

Pentru a evita cheltuirea unei funcții de apel, funcția poate fi descrisă ca inline, și pentru a oferi un acces mai rapid la parametrii, acestea pot fi descrise ca un registru. Ambele instrumente pot fi utilizate în mod abuziv, și trebuie evitată ori de câte ori există vreo îndoială cu privire la utilitatea lor.

Când funcția este numită, memorie suplimentară este alocată în conformitate cu parametrii formali, iar fiecare parametru formal este inițializat la argumentul său real corespunzător. Semantica parametri de transmisie semantică identică de inițializare. În special, tipul parametrului efectiv este mapat la tipul parametrului formal, și efectuează toate tipurile standard și anumite de conversie a utilizatorului. Există reguli speciale pentru vectorii de transport, înseamnă să treacă un parametru fără a verifica și mijloace pentru setarea parametrilor implicite.

void f (int val, int ref)

Când i se f (), Val ++ crește copia locală a primului parametru real, în timp ce ++ ref crește al doilea parametru real.

void f (Const mare ARG)

// valoarea «ARG» nu poate fi modificată

În mod similar, descrierea modului în care parametrul indicele const spune cititorului că valoarea obiectului indicat de funcția de indicator nu este schimbat.

int strlen extern (char * const); // de

char * strcpy extern (char * la, const char * de la);

strcmp int extern (const char *, const char *);

Importanța acestei practici crește dimensiunea programului.

Rețineți că parametrul care trece semantica sunt diferite de semantica atribuire. Este important pentru parametrii const, parametrii de referință și parametrii unor tipuri definite de utilizator.

Din funcția care nu este descris ca un gol, poate (și ar trebui) valoarea de returnare. Valoarea returnată este definită de declarația de returnare.

Funcția poate fi mai mult de un operator pentru a reveni:

Ca parametru care trece semantica, semantica valorilor funcție de înapoiere este identică cu semantica initializare. Valoarea returnată este considerată ca fiind un tip de întoarcere variabilă initializare. Tipul de retur de exprimare este verificată concordanța cu tipul de retur și executate toate tipurile standard și unele de conversie de utilizator.

întoarce 1; // convertit implicit la dublu (1)

întoarcere &local; // nu fac

Această eroare este mai puțin frecvente decât eroarea echivalentă atunci când se utilizează referințe:

întoarce locale; // taknedelayte

Din fericire, pentru acele valori de returnare previne compilator.

Iată un alt exemplu:

int f () // nu fac

Dacă funcțiile vectorului parametru este utilizat, atunci un pointer la primul element.

int strlen (char * const);

char v [] = «un vector»

Cu alte cuvinte, transmiterea ca parametru de tip T [] este convertit la T *. Prin urmare, elementul de atribuire modifică valoarea vectorului elementului vector parametru care este un parametru. Cu alte cuvinte, vectorul este diferit de toate celelalte tipuri în care vectorul nu este trimis (sau transmise) cu valoarea.

Dimensiunea vectorului este indisponibil funcția de apelare. Acesta poate fi inconfortabil, dar această dificultate poate fi eludată prin mai multe metode. Linia se termină cu un zero, astfel încât dimensiunea sa poate fi ușor de calculat. Pentru alți vectori pot transmite un al doilea parametru care specifică dimensiunea, sau pentru a determina tipul care conține un pointer și un indicator de lungime, și o transmite în schimb, pur și simplu vector.

void compute1 (int * vec_ptr, int vec_size); // odinsposob

struct vec

void compute2 (v vec);

Cu matrice multidimensionale tot mai complicat, dar de multe ori puteți utiliza în loc un vector de indicii care nu necesită o atenție specială.

«Mon», «tue», «căsători», «thu», «fri», «a stat», «soare»

Pe de altă parte, considerăm definiția unei funcții, care funcționează cu matrice bidimensionale. În cazul în care dimensiunea este cunoscută la momentul compilării, atunci nu există nici o problemă:

void print_m34 (int m [3] [4])







pentru (int i = 0; i<3; i++)

pentru (int j = 0; j<4; j++)

cout <<" " <

cout <<"\n";

Matricea, desigur, este încă trecut ca un pointer, iar dimensiunile sunt utilizate doar pentru comoditate de notație.

Prima dimensiune a matricei nu este legată de problema găsirii poziției elementului. Prin urmare, aceasta poate fi transmisă ca parametru:

void print_mi4 (int m [] [4], int dim1)

setări prestabilite

De multe ori, în cazul cel mai general, funcția necesită mai mulți parametri decât în ​​cazul cel mai simplu și mai frecvent utilizate. De exemplu, în fluxul de bibliotecă este o funcție hex (), generând un șir cu reprezentarea hexazecimală a întregului. Al doilea parametru este utilizat pentru a specifica numărul de caractere pentru a reprezenta primul parametru. În cazul în care numărul de caractere este prea mic pentru a reprezenta întreg, este trunchiat dacă este prea mare, șirul este căptușit cu spații libere. De multe ori programatorul nu-i pasă de numărul de caractere necesare pentru a reprezenta întreg, deoarece caractere suficiente. Prin urmare, la zero în al doilea parametru este determinat să „utilizeze cât mai multe caractere ca ai nevoie.“ Pentru a evita infundarea provocărilor programului, cum ar fi hex (i, 0), funcția este descrisă după cum urmează:

char * hex extern (long, int = 0);

Al doilea parametru de inițializare setarea implicită este. Aceasta este, în cazul în care apelul este dat doar o singură opțiune ca al doilea parametru este utilizat în mod implicit.

cout <<"**" <

cout <<"**" <

Setarea implicită este verificat de tip într-o funcție și se calculează la momentul apelului ei. Setarea implicită este posibilă numai pentru a cere cele mai noi parametri, astfel încât

int f (int = 0, char * = 0); // OK

int g (int = 0, int = 0, char *); // eroare

int f (int = 0, int, char * = 0); // eroare

Rețineți că, în acest context, un spațiu între și * = este (* = este un operator de atribuire) semnificative:

int urât (char * = 0); // eroare de sintaxă

Suprasarcină numele funcției

Ca regulă generală, pentru a da funcții diferite nume diferite - ideea este bună, dar atunci când unele dintre funcțiile face același lucru cu obiecte de tipuri diferite pot fi mai convenabil pentru a le da același nume. Utilizarea unui singur nume pentru o varietate de acțiuni pe diferite tipuri se numește supraîncărcare (supraîncărcare). Metoda este deja utilizat pentru C ++ operații de bază: în plus, există doar un singur nume, + dar poate fi folosită pentru a adăuga valorile tipurilor integrale, plutitoare, și pointer. Această idee este ușor de extins la operațiunile de prelucrare definite de utilizator, adică, funcții. Pentru a proteja programator de reutiliza accidental numele, numele poate fi utilizat pentru mai mult de o funcție numai în cazul în care este descrisă mai întâi ca congestionat.

În ceea ce privește compilator, singurul lucru în comun, ele au o funcție cu același nume, este numele. Probabil, ei sunt într-un anumit sens, însă, în limba și nici nu constrânge programator sau să-l ajute. Astfel, numele de funcții supraîncărcate - este cea mai mare parte de intrare pentru comoditate. Acest confort este mult în cazul funcțiilor cu nume comune, cum ar fi sqrt, de imprimare și deschis. În cazul în care numele este semnificativă semantically, așa cum este cazul pentru operațiuni, cum ar fi +, * și <<и в случае конструкторов, это удобство становится существенным.

Când apelați un f supraîncărcată (), compilatorul trebuie să înțeleagă care dintre funcțiile numite f ar trebui să se aplice. Acest lucru se realizează prin compararea tipurilor de parametrii actuali cu tipurile de parametrii formali ai o funcție numită f. Funcții de căutare care trebuie să apelați, efectuate în trei etape distincte:

Funcții de căutare corespunde exact să-l folosească și în cazul în care se constată;

Căutați funcția corespunzătoare folosind built-in de conversie și de a folosi orice funcție găsit; și

Căutați funcția corespunzătoare folosind conversia definită de către utilizator, iar în cazul în care setul de transformări este unic, folosește funcția găsit.

imprimare de suprasarcină (dublu), print (int);

Regula de potrivire exactă asigură că imprimă f 1 ca un întreg și 1.0 ca un număr în virgulă mobilă. Zero, char sau un parametru short int exact meci. În mod similar, float corespunde exact dublu.

Parametrii funcțiilor cu nume supraîncărcate ale regulilor de conversie standard C ++ nu sunt aplicate complet. De conversie, care pot distruge datele, nu sunt îndeplinite. Int rămân în lung, int în dublu, un zero lung, și zero în indicii de conversie duble: un pointer la zero, un vid de zero *, și un pointer la clasa derivata la un pointer la clasa de bază.

Aici este un exemplu în care este necesară conversia:

imprimare de suprasarcină (dublu), print (lung);

S-ar putea fi imprimată sau dublă, sau cât de mult timp. Ambiguitatea este rezolvată în mod explicit tipul de conversie (sau de imprimare (lung (a)), sau de imprimare (dublu (a))).

În conformitate cu aceste norme pot asigura că, atunci când eficiența sau acuratețea calculelor pentru tipurile utilizate sunt semnificativ diferite, algoritmul va folosi cel mai simplu (funcția).

pow dublu (dublu, dublu); // de

pow complex (dublu, complex); // de

pow complex (complex, int);

pow complex (complex, dublu);

pow complex (complex, complex);

Protsesspoiskapodhodyascheyfunktsiiignoriruet nesemnat și Const.

număr nespecificat de parametri

Pentru unele funcții pe care nu se poate specifica numărul și tipul de toți parametrii care pot fi așteptate în apel. Această funcție descrie completarea unei liste de descrieri ale parametrilor elipsă (.), Ceea ce înseamnă „și poate alte opțiuni.“

Aceasta specifică faptul că apelul ar trebui să fie printf cel puțin un parametru, char *, iar celălalt poate sau nu poate fi.

printf ( «Moeimya% s% s \ n», first_name, second_name);

printf ( ".. + = \ n.", 2,3,5);

Această caracteristică se bazează pe informații care nu sunt disponibile pentru compilatorul atunci când se interpretează lista de parametri. În cazul printf () în primul parametru este un șir format care conține secvențe de caractere speciale, care permit printf () să se ocupe în mod corect restul parametrilor. % S înseamnă „așteptați parametrul char *», de asemenea. înseamnă „așteptați parametrul int.“ Cu toate acestea, compilatorul nu știe, așa că nu poate fi sigur că parametrii de așteptat să aibă tip corespunzător.

printf ( «Numele meu% s% s \ n», 2);

Compilați și cel mai bun caz ar conduce la unele probleme ciudate cu aspect.

Evident, în cazul în care parametrul nu a fost descris, atunci compilatorul este nici o informație necesară pentru a fi efectuate pe ele de tip test și de conversie de tip. În acest caz, char sau transmisă ca short int, float și transmise ca dublu. Acest lucru nu este neaparat ceea ce este în așteptare pentru utilizator.

Utilizarea excesivă de puncte, cum ar fi sălbatic (.), dezactivează complet parametru tipuri de validare, lăsând programator deschis la o multitudine de probleme care sunt familiare programatori în C. într-un program bine conceput necesită cel mult câteva funcții pentru care tipuri de setări nu sunt complet definite. Pentru a avea grijă de tipurile de verificare, puteți utiliza funcțiile și funcțiile supraîncărcate cu setările implicite, în majoritatea cazurilor, în cazul în care în caz contrar ar trebui să lase tipuri neinvitat de parametri. Elipsă este necesară numai dacă modificați numărul de parametri și a parametrilor de tip. Cea mai comună utilizare de puncte în interfața de sarcină pentru funcțiile de bibliotecă C, care au fost identificate în momentul în care nu a existat nici o alternativă:

fprintf int extern (FILE *, char *.); // de

execl int extern (char *.); // de

abort int extern (.); // de

Să considerăm cazul scrierii funcției de eroare, care are un parametru întreg care indică gravitatea erorii, care este urmat de un număr arbitrar de rânduri. Ideea este de a face mesajul de eroare prin transmiterea fiecărui cuvânt ca parametru șir separat:

main (int argc, char * argv [])