6.1 Rekursiv funksiya- özü özünü çağıran funksiyaya deyilir. Rekursiya proqramlaşdırmada funksiya gövdəsində özünü çağıran proses kimi başa düşülür. Çox vaxt rekursiyadan istifadə proqram kodunun həcmini azaltmır. Həmçinin bir sıra prosedurların rekursiv variantları öz iterativ ekvivalentlərindən ağır işləyir. Buna səbəb funksiyanın dəfəli çağırışının sistem resurslarını çox işlətmısidir.
Müsbət cəhəti isə bəzi alqoritimlərin rekursiv realizasiyası onların iterativ ekvivalentlərindən asan başa gəlməsidir. Bundan başqa bəzi məsələlərin həlli ancaq rekursiv yolla mümkündür.
P1. Rekursiya və iterasiya ilə faktorialın hesablanması: #include using namespace std;
int factr(int n);
int fact(int n);
int main()
{
// rekursiya versiyasi.
cout << "4! beraberdir " << factr(4);
cout << '\n';
// iterativ versiya.
cout << "4! beraberdir " << fact(4);
cout << '\n';
return 0;
}
int factr(int n)
{
int answer;
if(n==1) return(1);
answer = factr(n-1)*n;
return(answer);
}
int fact(int n)
{
int t, answer;
answer =1;
for(t=1; t<=n; t++) answer = answer * (t);
return (answer);
}
Bu kodda cevir () -funksiyası öz sətir tipli arqumentini əks ardıcıllıq ilə düzməsində rekursiyadan istifadə edir #include using namespace std;
void cevir(char *s);
int main()
{
char str[] = "Bu testdir";
cevir(str);
return 0;
}
void cevir (char *s)
{
if(*s) cevir(s+1);
else return;
cout << *s;
}
Burada “cevir” funksiyası öz göstərici parametrinə nul verilmədiyini yoxlayır. Nul sətrin sonunu göstərir. Şərt ödəndikdə (*s!=null) “cevir” funksiyası özünü, öz yeni göstərici parametri (sətirdə növbəti simvola bərabər olan göstərici) ilə çağırır. Bu “içəri burulan” proses null göstəriciyə qədər təkrar olacaq. Göstərici sətr sonu (Null) qiyməti aldıqda “içəridən açılaraq qayıtma” prosesi başlayacaq və hər dəfə s simvolu çap olunacaq.
Nəticədə sətr sondan əvvələ çap olunacaq.
6.2. Funksiyanın yüklənməsi (Перегрузка функций-Function overloading) - bir funksiyanı bir neçə yolla(üsul ilə) işlətməyə imkan verən bir xüsusiyyətdir və hər üsul ilə bir iş yerinə yetirmək mümkündür.
Kompilyator tip və ya arqument sayına görə yüklənmiş funksiyaları fərqləndirir.
C-də C++ dan fərqli olaraq yüklənmiş funksiyalar dəstəkləmir.
// funksiyanın "Üçqat " yüklənməsi.
#include using namespace std;
void f(int i); // 1 tam tipli parametr
void f(int i, int j); // 2 tam tipli parametr
void f(double k); // Bir double tipli parametr
int main()
{
f (10); // f(int) çağırılması
f(10, 20); // f (int, int) çağırılması
f(12.23); // f(double) çağırılması
return 0;
}
void f(int i)
{
cout << " f(int) de i beraberdir " << i << '\n';
}
void f(int i, int j)
{
cout << " f(int, int) de i beraberdir " << i;
cout << " f(int, int) de j beraberdir " << j << '\n';
}
void f(double k)
{
cout << " f(double) de k beraberdir " << k << ' \n';
}
Yuxarıdakı nümunədə eyni adlı, lakin fərqli sayda arqumentlərlə üç funksiyamız var.
void f(int i);
void f(int i, int j);
void f(double k);
Funksiya çağırılan zamanı ötürülən parametrlərin sayı və ya tipindən asılı olaraq kompilyatorun hansı funksiyanın çağırılmalı olduğu müəyyən edilir, buna görə də funksiyaların yüklənməsi polimorfizmin nümunəsi hesab olunur, çünki fərqli şərtlərdə fərqli çıxış olur. Hansı funksiyanın çağırılacağı kompilyasiya zamanı təyin olunduğundan, bu kompilyasiya vaxtı polimorfizm (Compile time Polymorphism) adlanır. (Polimorfizmin digər nümunələri ilə irəlidə tanış olacağıq!)
Yüklənmiş funksiyaların müsbət cəhəti kimi C standart kitabxanasından olan abs(), labs() и fabs()baxaq. Bu funksiyalarmüvafiq olaraq int, long, double tipli dəyişənlərin modulunu hesablayır. C++ da isə ( başlıq faylında elan olunmuş) abs()yüklənmiş funksiyası hər üç dəyişən tipi ilə işləyir. Bu funksiyanın müxtəlif dəyişən tipləri ilə necə işləməsini başa düşmək məqsədi ilə c++ kitabxanasındakı olan modul hesablayan funksiyasını təkrar yazaq:
#include using namespace std;
int myabs(int i);
double myabs(double d);
long myabs(long l);
int main()
{
cout << myabs(-10) << "\n";
cout << myabs(-11.0) << "\n";
cout << myabs(-9L) << "\n";
return 0;
}
int myabs(int i)
{
cout << " int- myabs(): ";
if(i<0) return -i;
else return i;
}
double myabs(double d)
{
cout << " double- myabs(): ";
if(d<0.0) return -d;
else return d;
}
long myabs(long l)
{
cout << " long- myabs(): ";
if(1<0) return -1;
else return 1;
}