Postoje slučajevi kada funkcija f poziva funkciju g, a funkcija g poziva funkciju f. Koju ćeš pre definisati? Ako definišeš prvo f, ona ne može da poziva g i obrnuto. Međutim, ako ih prvo deklarišeš, onda ih možeš definisati u bilo kom redosledu. To je slučaj kada prividno ne možeš da izbegneš deklarisanje funkcija pre njihovih definicija. U stvari možeš tako što ćeš funkcionalnost obe funkcije da objediniš u jednu funkciju, koja samu sebe poziva. Ovo je najređa situacija kada ti u praksi treba deklaracija pre definicije. Kasnije ću navesti i druge slučajeve.
Primer: Ako bi pisao program za igranje šaha, onda se svakoj poziciji pridružuje neka numerička vrednost. Vrednost 0 znači da ni jedna strana nije u prednosti, negativne vrednosti da je crni u prednosti i to utoliko većoj što je vrednost negativnija (dalja od nule), a pozitivne bi značile da je beli u prednosti i to utoliko većoj što je vrednost pozitivnija (dalja od nule). Dakle, crni se trudi da smanji vrednost pozicije, a beli da je poveća. Ako je crni na potezu, onda je vrednost pozicije minimum od vrednosti pozicija u koje se može preći jednim potezom crnog, a ako je beli na potezu, onda je vrednost pozicije maksimum vrednosti pozicija u koje se može preći jednim potezom belog. No, u jednom trenutku se mora stati i drugačije oceniti vrednost pozicije (statička vrednost pozicije). Funkcije min i max se mogu napisati ovako:
Code (cpp):
bool whitesTurn(Position p);
int possibleMoves(Position p);
Position makeMove(Position p, int moveNum);
int staticValue(Position p);
int min(Position p, int depth);
int max(Position p, int depth);
int min(Position p, int depth)
{
if (depth <= 0) {
return staticValue(p);
}
int currentMin = INT_MAX;
int moves = possibleMoves(p);
for (int i = 0; i < moves; ++i) {
Position q = makeMove(p, i);
int value = max(q, depth - 1);
if (value < currentMin) {
currentMin = value;
}
}
return currentMin;
}
int max(Position p, int depth)
{
if (depth <= 0) {
return staticValue(p);
}
int currentMax = INT_MIN;
int moves = possibleMoves(p);
for (int i = 0; i < moves; ++i) {
Position q = makeMove(p, i);
int value = min(q, depth - 1);
if (value > currentMax) {
currentMax = value;
}
}
return currentMax;
}
int minmax(Position p, int depth)
{
if (depth <= 0) {
return staticValue(p);
}
bool whitesTurn = whitesTurn(p);
int currentValue = whitesTurn ? INT_MIN : INT_MAX;
int moves = possibleMoves(p);
for (int i = 0; i < moves; ++i) {
Position q = makeMove(p, i);
int value = minmax(q, depth - 1);
if ((whitesTurn && value > currentValue) || whitesTurn == false && value < currentValue)) {
currentValue = value;
}
}
return currentValue;
}
Dakle, može sa dve funkcije (min i max), a može i sa jednom (minmax).
Drugi slučaj kada ti treba deklaracija pre definicije je kada treba koristiti konvencije o pozivanju funkcija nekog drugog programskog jezika.
Primer:
Code (cpp):
extern "C" double add(double x, double y);
double add(double x, double y)
{
return x + y;
}
Treći i najčešći slučaj je kada pišeš program iz više modula. Modul (ili jedinica za prevođenje) je jedan cpp fajl zajedno sa svim zaglavljima koje neposredno ili posredno uključuje. Neka funkcija može biti definisana u jednom modulu, a da se koristi u drugom. Taj drugi modul mora znati njen prototip. Recimo da je funkcija definisana u bib.cpp, a da se koristi u main.cpp. Uobičajeno je da postoji zaglavlje bib.h u kome je deklarisano sve što se definiše u bib.cpp, a što drugi moduli treba da vide, a da onda main.cpp ima direktivu #include "bib.h", kao i da bib.h ima oblik
Code (cpp):
#ifndef BIB_H
#define BIB_H
// Some contents
#endif
Četvrti slučaj, koji je najčešći posle trećeg je da pišeš biblioteku. Ona ti je zapravo kao zaseban modul, koji se zasebno kompajlira i lepo zapakuje, tako da veže iste napomene kao u trećem slučaju.
Nije bitno koji su zaključci izvučeni, već kako se do njih došlo.