Bir main funksiyasından ibarət olan aşağıdakı sadə proqrama baxaq:
#include <iostream>
using namespace std;
int main()
{cout<<"Hello World";
return 0;
}
Burada birinci sətir int main() – funksiyanın başlığıdır və operatorlardan fərqli olaraq ondan sonra “;”işarəsi qoyulmur. Funksiyanın başlığı nəticənin tipindən, funksiyanın adından və parametrlər siyahısından ibarət olur. main sözünün əvvəlindəki verilənlər tipi – qaytarılan tipdir, main – funksiyanın adıdır, () – isə parametrlər siyahısını saxlayır (bu misalda siyahı boşdur).
Funksiyanın başlığından sonra { mötərizəsi ilə funksiyanın gövdəsi başlayır və bağlayıcı } mötərizəsi ilə qurtarır. Qeyd edək ki, funksiyanın gövdəsində başqa mötərizələr də iştirak edə bilər, məsələn, if şərt operatorunda və ya dövr operatorunda bir neçə operatorun yerləşdirilməsi üçün istifadə edilə bilər.
Funksiyanın gövdəsi bir və ya bir neçə operatordan ibarət ola bilər. Baxılan misalda funksiyanın gövdəsi iki operatordan ibarətdir. Sonuncu operator return 0 - qayıdış operatorudur. Əgər qayıtma tipi void -dirsə, onda qayıdış operatorunu qoymaq məcburi deyil.
Funksiyanın gövdəsi və başlığı birlikdə funksiyanın təyini adlanır. Əgər funksiya təyin olunmayıbsa, onda o işləməyəcək. Funksiya təyin olunduqda isə çağırıldığı zaman işləyəcək. Funksiya adətən kodda çağırılır, yalnız main funksiyası istisna təşkil edir. main funksiyası proqram buraxılarkən avtomatik olaraq çağırılır.
6.2. Funksiyanın təyin olunması
Əvvəlki bənddəki proqrama baxaq və kodu iki funksiyaya ayıraq: main və printmessage (“Hello World” – ü çıxarır). Şərhlər (// ilə başlayan) printmessage funksiyasının təyininin başlanğıc və sonunu, həmçinin bu funksiyanın çağırılmasını işarə edirlər:
# include < iostream >
using namespace std;
// printmessage funksiyasinin təyininin baslangıcı
void printmessage (void)
{
cout <<”Hello World”;
}
//printmessage funksiyasının təyininin sonu
int main()
{
printmessage (); // printmessage funksiyasının cağırılması
return 0;
}
Burada əvvəlcə printmessage funksiyası təyin olunur. Funksiyanın adının qarşısındakı void xidməti sözü onu göstərir ki, printmessage funksiyası qiymət qaytarmır. Funksiyanın adından sonra mötərizə daxilindəki void sözü onu göstərir ki, bu funksiyanın parametrləri yoxdur. Mötərizədə heç nə yazılmaya da bilər, bu funksiyanın adından sonra void yazılışı ilə ekvivalentdir.
printmessage funksiyasının gövdəsində ekrana “Hello World” məlumatını çıxaran bir parametr yerləşir. Funksiyanın gövdəsində qayıtma operatorunu yazmaq vacib deyil, ona görə ki, əgər qayıtmanın tipi void -disə, onda belə hesab olunur ki, qayıtma operatoru işləməmişdir. Lakin aşkar şəkildə qayıtma operatorunu yazmaq olar. Onda printmessage funksiyası belə olar:
void printmessage (void)
{
cout <<”hello world”;
return;
}
6.3. Funksiyanın çağırılması
Əvvəlki bənddəki printmessage funksiyası main funksiyasına
printmessage ();
sətri şəklində çağırılır. Bu misalda printmessage funksiyası main funksiyasından çağırıldığına görə çağırılan funksiyadır. Baş mötərizə onu göstərir ki, bu funksiya ilə heç bir qiymət ötürülmür. Proqramın işləmə qaydası aşağıdakı kimidir:
1) icra prosesi main funksiyası ilə başlayır;
2) sonra main funksiyasının birinci operatoru- printmessage () funksiyası çağırılır;
3) bundan sonra icraetmə printmessage funksiyasına yönəlir, onun birinci operatoru yerinə yetirilməyə başlayır və “Hello World” məlumatı ekrana çıxarılır.
4) printmessage funksiyasının işi sona çatdıqdan sonra proqram yenidən main funksiyasına, növbəti yerinə yetirilməyən və proqramın sonuncu operatoru olan return 0 – operatoruna qoşulur.
6.4. Prototipin yaradılması
Proqramın icrası main funksiyası ilə başladığından, onda məntiqi olaraq belə nəticəyə gəlmək olar ki, main funksiyası printmessage funksiyasından əvvəldə yerləşməlidir.Yəni,
#include <………..>
using namespace std;
int main()
{
printmessage();
return 0;
}
void printmessage (void)
{
cout <<”hello world”;
}
Lakin belə kod kompilyasiya olunmayacaq, printmessage () sətri işıqlanacaq və “undeclared identifier” səhvi haqqında məlumat veriləcək.
Bu səhvin səbəbi ondan ibarətdir ki, kompilyator kodu yuxarıdan aşağıya keçərkən funksiyanın çağrılmasını görərək onun adını, qayıtma tipini və parametrlərini artıq bilməlidir. Lakin printmessage funksiyası main funksiyasından əvvəl təyin olunduqda isə, kompilyator main funksiyasında printmessage () müraciətini tapır, lakin onun haqqında hələlik heç nə bilmir: nə onun adını, nə qaytarılan qiymətin tipini, nə parametrləri.
Bu problemin həlli – bütün funksiyaların təyininin main funksiyasına qədər olmasından ibarətdir. Düzdür, bu halda proqram daha az oxunaqlı olacaq. Qeyd etmək lazımdır ki, funksiyaların yerləşmə ardıcıllığından asılı olmayaraq proqramın işi həmişə main funksiyası ilə başlayır. Funksiyaların sayı çox olduqda isə main funksiyası onları bir- birinin ardınca çağırır. Mürəkkəb proqramlarda, yəni bir funksiya digər bir funksiyanı, o isə başqa bir funksiyanı və s. çağırdıqda funksiyaların təyin olunma ardıcıllığında səhv olmaması üçün main -dən başqa bütün funksiyaların prototipinin yaradılması zəruridir. Aşağıdakı proqramda printmessage () funksiyası üçün prototipin necə yaradılması göstərilir:
# include <inter>
using namespace std;
void printmessage (void);// bu prototipdir
int main()
{
printmessage();
return 0;
}
void printmessage (void)
{
cout <<”hello world”;
}
Beləliklə, prototip bütün funksiyaların təyinindən yüksəkdə dayanır və kompilyator kodu yuxarıdan aşağıya keçərkən hər bir funksiyanın qarşısında dəqiq prototip görür. Onu da qeyd edək ki, prototip funksiyasının başlığına oxşayır, əsas fərq ondadır ki, o operatordur və ondan sonra həmişə nöqtə vergül yazılır.
Lokal dəyişənlər
İndiyə qədər bütün dəyişənlər main funksiyasının yuxarı hissəsində yerləşirdi. Bir main funksiyası olan proqramlarda bu dəyişənlərə proqramın istənilən yerində müraciət etmək olar. Lakin kodu bir neçə müxtəlif funksiyaya böldükdə dəyişənin görünmə oblastı və mövcudluq zamanı ilə bağlı problemlər yaranır.
Eyni bir funksiyanı bir neçə dəfə çağırmaq olar. Aşağıdakı proqramda printmessage funksiyası istifadəçinin istədiyi qədər çağırılır və hər dəfə ekrana bu funksiyanın çağrılma sayı çıxarılır:
# include <inter>
using namespace std;
void printmesage (void);
int main()
{
int times=0;
char choice;
do {
cout <<”Enter Q to quit, any other character to continue:”;
cin >> choice;
if (choice ==’Q’)
cout << ”input stopped”;
else printmessage ();
} while (choice!=’Q’);
return 0;
}
void printmesage (void)
{
times + +;
cout << ”this function colled”<< times << ”times \ n”;
}
Bu kod kompilyasiya olunmayacaq, belə ki, printmessage funksiyasında times dəyişəni elan olunmayıb (“undeclared identifier”). Kompilyatorun bu səhvini times dəyişəninin elanını printmessage funksiyasına köçürməklə aradan qaldırmaq olar:
void printmessage (void)
{
int times=0;
times ++;
cout << “ this function called” << times << ”times \ n;
}
times dəyişəni printmessage funksiyası üçün lokal dəyişəndir, çünki həmin funksiyanın daxilində təyin olunub. Ona görə də times lokal dəyişən olduğundan hər dəfə printmessage funksiyası çağırılarkən o yaradılır, hər dəfə printmessage funksiyasının icrası sona çatdıqdan sonra o ləğv olunur. Beləliklə, ikinci dəfə printmessage funksiyası çağırıldıqda times dəyişəni printmessage funksiyasının birinci çağırışında yaradılan times dəyişəninin davamı olmur. printmessage funksiyasının hər bir çağırışında times dəyişəni yenidən yaradılır.
Qeyd edək ki, funksiyaya müxtəlif müraciətlər zamanı dəyişənin qiymətini iki üsulla saxlamaq olar. Birincisi, lokal dəyişən əvəzinə qlobal dəyişən istifadə etməklə, ikincisi, statik lokal dəyişəndən istifadə etməklə.
Qlobal dəyişənlər
“Qlobal” termini onu göstərir ki, dəyişən bütün proqram daxilində görünmə oblastına malikdir, ona görə də onun mövcudluq vaxtı yalnız proqram öz işini sona çatdırdıqdan sonra qurtarır. Dəyişənin qlobal olması üçün onu funksiyaların prototipləri ilə bütün funksiyaların tipinə qədər elan etmək lazımdır:
# include <inter>
using namespace std;
void printessage ();
int times;
int main()
{
times=0;
char choice;
do{
cout <<”Enter Q to quit, any other character to continue:”;
cin >> choice;
if (choice==’Q’)
cout <<”input stopped”;
else
printmessage();
} while (choice!=’Q’);
return 0;
}
void printmessage (void)
{
times++;
cout << ”this function called” << times <<”times \ n”;
}
Qeyd edək ki, dəyişənlərin qloballaşdırılması onlara proqramın istənilən yerində müraciət etməyə imkan versə də, qlobal dəyişənin nə səbəbə düzgün olmayan qiymət almasını tapmaq prosesi çətinləşir. Ona görə də imkan daxilində proqramçıların qlobal dəyişənlərdən istifadə etməmələri məsləhətdir. Qlobal dəyişənlərə alternativ olaraq statik lokal dəyişənləri göstərmək olar.