2.8. Supra?nc?rcarea func?iilor

2.8. Supra?nc?rcarea func?iilor

?n limbajul C nu exist? posibilitatea de a crea mai multe func?ii cu unul ?i acela?i nume. Presupunem c? avem necesitate de o func?ie care afl? valoarea maximal? din dou? pentru diferite tipuri de date. ?n C trebuie s? invent?m c?te un nume de func?ie pentru fiecare tip de date ale parametrilor, cum ar fi, de exemplu, imax() pentru date de tipul int, fmax() pentru date de tipul float, dmax() pentru date de tipul double etc.

?n C++ dou? sau mai multe func?ii diferite pot avea unul ?i acela?i nume, ?ns? ele trebuie s? difere prin tipul ?i/sau num?rul de parametri.

Func?iile care au unul ?i acela?i nume ?i difer? ?ntre ele prin tipurile parametrilor ?i/sau num?rul de parametri se numesc func?ii supra?nc?rcate (engl. overload). Procesul de creare a func?iilor respective se nume?te supra?nc?rcare (engl. overloading).

Deoarece nimic nu a fost spus despre tipul rezultatului returnat, reiese c? func?iile supra?nc?rcate pot s? posede diferite tipuri ale rezultatului de returnare.

Urm?torul exemplu ilustreaz? modul de supra?nc?rcare a func?iilor:

#include "iostream.h"
 
int max(int i1, int i2) // prima func?ie max() afl? elementul maximal               
{                       // din dou? valori de tipul int    
   return i1>i2 ? i1 : i2;
}
 
double max(double d1, double d2) // a doua func?ie max() afl?                   
{                                // elementul maximal din dou? valori 
                                 // de tipul double
   return d1>d2 ? d1 : d2;
}
 
char* max(char* s1, char* s2) // afl? ?irul maximal din dou? 
{                            
   int i=0;
   while( (*(s1+i)!='\0') && (*(s1+i)==*(s2+i)) )
      i++;
   return *(s1+i)>*(s2+i)? s1 : s2;
}
 
void main()
{
   int i=2, k=10;
   cout << "max(" << i << ", " << k << ")="
        << max(i, k) << endl;
   cout << "max(" << 3.14 << ", " << 2.25 << ")="
        << max(3.14, 2.25) << endl;
   char *s1="abcd";
   char *s2="abd";
   cout << "s1=\"" << s1 << "\"" << endl;
   cout << "s2=\"" << s2 << "\"" << endl;
   cout << "max(s1, s2)=\"" << max(s1, s2) << "\""
        << endl;
   cout << "max(\"" << "abdc" << "\", \"" << "abcd"
        << "\")=\"" << max("abdc", "abcd") << "\""
        << endl;
 
   char c; cin >> c;
}


?n acest program mai ?nt?i a fost descris? func?ia max() care afl? ?i ?ntoarce valoarea maximal? din dou? valori date de tipul int. Apoi, aceasta func?ie a fost supra?nc?rcat? de dou? ori. O dat?  pentru aflarea valorii maximale din dou? valori de tipul double ?i a doua oar? pentru aflarea ?irului maximal din cele dou?. Algoritmul pentru ?iruri de caractere difer? esen?ial de cel pentru numere. De fapt, la realizarea lui putea fi folosit? ?i func?ia strcmp(), dar ea nu a fost utilizat? ?n acest exemplu, pentru a exclude necesitatea de a conecta fi?ierul antet "string.h".

?n func?ia main() se demonstreaz? apelurile func?iilor supra?nc?rcate. Programul afi?eaz? urm?torul text:

max(2, 10)=10
max(3.14, 2.25)=3.14
s1="abcd"
s2="abd"
max(s1, s2)="abd"
max("abdc", "abcd")="abdc"

Acest text arat? rezultatele de apelare a func?iilor supra?nc?rcate. Prelucr?nd apelurile func?iilor supra?nc?rcate (max(i, k), max(3.14, 2.25), max(s1, s2), max("abdc", "abcd")), compilatorul se orienteaz? dup? tipurile argumentelor ?i decide care din cele trei func?ii supra?nc?rcate trebuie s? fie apelat? ?n fiecare caz concret.

Nu este neap?rat ca func?iile supra?nc?rcate s? fac? unul ?i acela?i lucru. ?n principiu, ele pot s? difere, ?i s? difere esen?ial. De exemplu, putem supra?nc?rca func?ia max() pentru tipul double ?n a?a mod ca ea s? calculeze ?i s? ?ntoarc?, de exemplu, r?d?cina p?trat? din suma p?tratelor a dou? argumente. ?ns?, nu se recomand? de a face a?a ceva. Ar fi de dorit ca func?iile supra?nc?rcate cu unul ?i acela?i nume s? fie ?nrudite din punctul de vedere al sensului lor.

Cum a fost deja men?ionat, func?iile supra?nc?rcate trebuie s? difere prin tipul ?i/sau num?rul de parametri. Dac?, de exemplu, ?n programul precedent ad?ug?m urm?toarea supra?nc?rcare a func?iei max():

double max(int i1, int i2)
{
   return i1>i2 ? i1 : i2;
}


atunci programul devine gre?it, fiindc? la apelurile de tipul max(i, k) compilatorul nu va ?tie care din dou? func?ii int max(int i1, int i2) sau double max(int i1, int i2) trebuie s? fie apelat?. Compilatorul nu va admite a?a ceva ?i va afi?a un mesaj de eroare de tipul: "Earlier declaration of 'max(int,int)'". Programul nu va fi compilat cu succes, cu at?t mai mult el nu va fi rulat.

Limbajul C++, ca ?i limbajul C, admite conversii automate dintr-un tip ?n alt tip, mai ales la apelarea func?iilor. De aceea, la supra?nc?rcarea func?iilor apare problema de ambiguitate, c?nd pentru dou? sau mai multe func?ii supra?nc?rcate compilatorul nu poate s? stabileasc? care anume din aceste func?ii supra?nc?rcate trebuie s? fie apelat?. De exemplu, dac? ad?ugam ?n func?ia main() din exemplul precedent instruc?iunea:

cout << max(6.28, 5) << endl;

programul va deveni gre?it, fiindc? ?nt?lnind apelul max(6.28, 5) compilatorul nu va ?tie care din dou? func?ii int max(int i1, int i2) sau double max(double d1, double d2) trebuie s? fie apelat?. ?n a?a caz se spune c? aceast? instruc?iune este ambigu?, iar a?a situa?ie se nume?te ambigu? ?i este o eroare. Compilatorul ?n a?a caz va afi?a ceva de tipul: ”Ambiguity between 'max(int,int)' and 'max(double,double)'” ?i programul nu va fi compilat cu succes ?i, deci, nu va fi rulat. ?n acest caz trebuie de precizat anume care func?ie trebuie s? fie apelat?. Dac? vom scrie instruc?iunea a?a:

cout << max(6.28, (double)5) << endl;

atunci va fi apelat? func?ia double max(double d1, double d2) ?i va fi afi?at 6.28.

Dac? vom scrie instruc?iunea a?a:

cout << max((int)6.28, 5) << endl;

atunci va fi apelat? func?ia int max(int i1, int i2) ?i va fi afi?at 6.

Problema de ambiguitate poate s? apar? ?i din cauza transmiterii parametrilor prin referin??. Dac?, de exemplu, vom mai insera, printre func?iile supra?nc?rcate ?n programul de mai sus, ?i urm?toarea func?ie, care va fi compilat? cu succes:

int max(int &i1, int &i2)
{
   return i1>i2 ? i1 : i2;
}


atunci va fi ambiguu orice apel de tipul max(i, k), fiindc? compilatorul nu va ?ti care din cele dou? func?ii max() (cea cu transmiterea parametrilor prin valoare sau cea cu transmiterea parametrilor prin referin??) trebuie s? fie apelat?. ?n acest caz compilatorul va afi?a mesajul de eroare: ”Ambiguity between 'max(int,int)' and 'max(int&,int&)'”, ?n timp ce apelul max(8, 3) va fi corect, deoarece ?n cazul nostru constantele nu pot fi transmise prin referin?e; astfel, compilatorul va alege func?ia int max(int i1, int i2). Din aceste considerente, nu va fi ambiguu nici apelul max((const int)i, (const int)k), la care argumentele sunt convertite explicit la constante de tipul int.

Compilatorului ?i este suficient s? precizeze numai printr-un parametru func?ia care trebuie s? fie apelat?. Urm?toarele apeluri nu sunt ambigue ?n exemplul discutat: max((const)i,(const)k), max((const)i,k), max(i,(const)k), max(i,5), max(4,k). Situa?ia se va schimba, dac? vom ?nlocui func?ia int max(int &i1, int &i2) cu int max(const int &i1, const int &i2). Cercetarea  acestui caz r?m?ne ca exerci?iu.

?nc? un izvor de ambiguitate reprezint? folosirea parametrilor implici?i ?n func?iile supra?nc?rcate. De exemplu, nimic nu ne ?mpiedic? s? inser?m ?n programul de mai sus o supra?nc?rcare a func?iei max() care va afla ?i va ?ntoarce valoarea maximal? din trei valori de tipul int. Aceast? supra?nc?rcare poate ar?ta astfel:

int max(int i1, int i2, int i3)
{
   return i1>i2 ? (i1>i3 ? i1 : i3) : (i2>i3 ? i2 : i3);
}


?i dac? ?n func?ia main() mai inser?m instruc?iunea:

cout << "max(7, 3, 9)=" << max(7, 3, 9) << endl;

ea ne va afi?a:

max(7, 3, 9)=9

c?nd va fi ?ndeplinit? ?n func?ia main(). Adic?, aici totul este ?n regul?. ?ns?, dac? vom insera ?n programul de mai sus versiunea urm?toare a func?iei max() cu trei parametri, printre care cel pu?in unul va avea valoarea implicit?, ?n loc de versiunea precedent?:

int max(int i1, int i2, int i3=0)
{
   return i1>i2 ? (i1>i3 ? i1 : i3) : S(i2>i3 ? i2 : i3);
}


atunci programul devine gre?it, fiindc? orice apel de tipul max(i, k) devine ambiguu ?i provoac? din partea compilatorului mesajul de tipul: "Ambiguity between 'max(int,int)' and 'max(int,int,int)'". ?ntr-adev?r, compilatorul nu ?tie care dintre cele dou? func?ii max() trebuie s? fie apelat?: cea cu doi parametri sau cea cu trei av?nd valoarea implicit? 0 pentru parametrul trei.

Deci, supra?nc?rc?nd func?iile, programatorul trebuie permanent s? ?in? cont de posibilitatea provoc?rii ambiguit??ilor.

Supra?nc?rcarea func?iilor este unul dintre mecanismele care asigur? proprietatea de polimorfism ?n C++ ca limbaj de programare orientat spre obiecte.

Pe l?ng? no?iunea de supra?nc?rcare vom folosi ?i no?iunea de suprascriere a func?iilor.

 

Prin suprascrierea (engl. overriding) func?iei vom ?n?elege ?nlocuirea ?ntr-un domeniu de ac?iune a unei func?ii cu o alt? func?ie al c?rei antet acoper? antetul func?iei suprascrise. Func?ia suprascris? r?m?ne ?n existen?? ?i poate fi apelat? ?n acest domeniu prin precizare suplimentar?.

Un exemplu de suprascriere este suprascrierea unei func?ii membre mo?tenite ?ntr-o clas? derivat? (a se vedea tema „Suprascrierea ?i supra?nc?rcarea func?iilor membre ?n clasa derivat?”).
_________________________
Autorul: dr.conf. S. Pereteatcu

рассказать друзьям и получить подарок

Оставить комментарий

Ваш email не будет опубликован. Обязательные поля отмечены *

Вы можете использовать это HTMLтеги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Translate Переводчик

Подписка на новости

SmartResponder.ru
Ваш e-mail: *
Ваше имя: *

Хостинг для Wordpress сайтов