Fonksiyon Tanımlama ve Çağırma
Bir mutfakta yemek yapıyorsun. Her seferinde sıfırdan "önce tavayı al, yağı koy, ısıt..." demek yerine bir tarif kartın var: "Yumurta pişir" diyorsun ve adımlar otomatik uygulanıyor. İşte fonksiyon tam olarak bu tarif kartıdır — bir işi paketleyip isim verirsin, sonra o ismi çağırarak işi tekrar tekrar yaptırırsın.
Fonksiyonlar programlamanın temel yapı taşıdır. Kodu organize eder, tekrarı önler ve büyük problemleri küçük parçalara böler. Bu derste fonksiyon tanımlamayı, çağırmayı ve C++'ta fonksiyonların nasıl çalıştığını sıfırdan öğreneceksin.
Fonksiyon Nedir?
Fonksiyon, belirli bir görevi yerine getiren isimlendirilmiş kod bloğudur. Bir kere yazarsın, istediğin kadar çağırırsın.
Fonksiyonsuz dünya:
// Aynı hesaplamayı 3 kez yapıyoruz — tekrar, tekrar, tekrar
double alan1 = 3.14159 * 5.0 * 5.0;
double alan2 = 3.14159 * 8.0 * 8.0;
double alan3 = 3.14159 * 12.0 * 12.0;Fonksiyonlu dünya:
double daireAlani(double yaricap) {
return 3.14159 * yaricap * yaricap;
}
double alan1 = daireAlani(5.0);
double alan2 = daireAlani(8.0);
double alan3 = daireAlani(12.0);İkinci versiyon daha kısa, daha okunabilir ve formülde hata varsa tek bir yerde düzeltirsin.
Fonksiyon Söz Dizimi
C++'ta bir fonksiyon tanımının dört parçası var:
dönüşTipi fonksiyonAdı(parametre1Tipi param1, parametre2Tipi param2) {
// fonksiyon gövdesi
return değer; // dönüş tipi void değilse
}Dönüş tipi: Fonksiyonun geriye döndürdüğü değerin tipi (
int,double,string,boolvb.)Fonksiyon adı: Fonksiyonu çağırmak için kullandığın isim
Parametreler: Fonksiyona verilen girdi değerleri (virgülle ayrılır)
Gövde: Fonksiyonun yaptığı iş (süslü parantez içinde)
#include <iostream>
using namespace std;
// Fonksiyon tanımı
int topla(int a, int b) {
int sonuc = a + b;
return sonuc;
}
int main() {
// Fonksiyon çağrısı
int s = topla(3, 5);
cout << "3 + 5 = " << s << endl; // 8
// Doğrudan kullanım
cout << "10 + 20 = " << topla(10, 20) << endl; // 30
return 0;
}Fonksiyon çağrıldığında şunlar olur:
Argümanlar (3 ve 5) parametrelere (
aveb) kopyalanırGövde çalışır (
sonuc = 3 + 5 = 8)returnile değer geri dönerÇağıran yerde bu değer kullanılır
void Fonksiyonlar — Değer Döndürmeyen
Her fonksiyonun bir değer döndürmesi gerekmez. Sadece bir iş yapıp biten fonksiyonlar için void kullanılır.
#include <iostream>
#include <string>
using namespace std;
void selamla(string isim) {
cout << "Merhaba, " << isim << "!" << endl;
// return yok — void fonksiyon
}
void cizgiCiz(int uzunluk) {
for (int i = 0; i < uzunluk; i++) {
cout << "-";
}
cout << endl;
}
int main() {
selamla("Ali"); // Merhaba, Ali!
cizgiCiz(20); // --------------------
selamla("Ayşe"); // Merhaba, Ayşe!
return 0;
}void fonksiyonlar ekrana yazdırma, dosyaya yazma, bir durumu değiştirme gibi "yan etki" (side effect) üreten işler için kullanılır.
void Fonksiyonda return
void fonksiyonlarda return; (değersiz) kullanarak fonksiyondan erken çıkabilirsin:
void yasKontrol(int yas) {
if (yas < 0) {
cout << "Geçersiz yaş!" << endl;
return; // Fonksiyondan erken çık
}
if (yas >= 18) {
cout << "Yetişkin" << endl;
} else {
cout << "Çocuk" << endl;
}
}return İfadesi
return iki iş yapar:
Fonksiyonun çalışmasını sonlandırır
Bir değer döndürür (void hariç)
#include <iostream>
using namespace std;
int mutlakDeger(int x) {
if (x >= 0) {
return x; // Pozitifse olduğu gibi döndür
}
return -x; // Negatifse işaretini değiştir
}
// Birden fazla return olabilir — ilk çalışan kazanır
bool ciftMi(int n) {
if (n % 2 == 0) {
return true;
}
return false;
// Daha kısa yazım:
// return n % 2 == 0;
}
int main() {
cout << mutlakDeger(-7) << endl; // 7
cout << mutlakDeger(3) << endl; // 3
cout << boolalpha;
cout << ciftMi(4) << endl; // true
cout << ciftMi(7) << endl; // false
return 0;
}⚠️ Dikkat: Void olmayan bir fonksiyonda
returnunutursan, fonksiyon tanımsız davranış (undefined behavior) sergiler. Derleyici uyarı verir ama program beklenmedik sonuçlar üretebilir. Her code path'te return olmalı.
// KÖTÜ — else dalında return yok
int buyukOlan(int a, int b) {
if (a > b) {
return a;
}
// b >= a durumunda ne dönecek? Tanımsız davranış!
}
// İYİ — her durumda return var
int buyukOlan_duzeltilmis(int a, int b) {
if (a > b) {
return a;
}
return b;
}Fonksiyon Prototipi (Declaration vs Definition)
C++ kodunu yukarıdan aşağıya okur. Bir fonksiyonu çağırmadan önce derleyicinin o fonksiyonu tanıması gerekir. İki yol var:
Yol 1: Fonksiyonu Çağırmadan Önce Tanımla
#include <iostream>
using namespace std;
// Tanım main'den ÖNCE
int kare(int x) {
return x * x;
}
int main() {
cout << kare(5) << endl; // Çalışır
return 0;
}Yol 2: Prototip (Declaration) + Sonradan Tanım
#include <iostream>
using namespace std;
// Prototip — fonksiyonun "kimlik kartı"
int kare(int x); // Sadece imza, gövde yok
double topla(double, double); // Parametre isimleri opsiyonel
int main() {
cout << kare(5) << endl; // 25
cout << topla(3.5, 2.1) << endl; // 5.6
return 0;
}
// Tanım — fonksiyonun gerçek gövdesi
int kare(int x) {
return x * x;
}
double topla(double a, double b) {
return a + b;
}Prototip, derleyiciye "böyle bir fonksiyon var, adı şu, parametreleri şu tipte, dönüş tipi şu" der. Gövdesi daha sonra yazılır.
Prototip Neden Önemli?
Küçük programlarda fark etmez ama büyük projelerde fonksiyonlar farklı dosyalarda olur. Header dosyalarında (.h) prototipler, kaynak dosyalarında (.cpp) tanımlar bulunur. Bu yapıyı ilerideki derslerde detaylı göreceksin.
// matematik.h — prototipler
int topla(int a, int b);
int cikar(int a, int b);
// matematik.cpp — tanımlar
int topla(int a, int b) { return a + b; }
int cikar(int a, int b) { return a - b; }
// main.cpp — kullanım
#include "matematik.h"
int sonuc = topla(3, 5);💡 İpucu: Prototipte parametre isimleri yazmak zorunlu değildir (
int topla(int, int);geçerli). Ama okunabilirlik için isim yazmak iyi bir alışkanlıktır.
main() Fonksiyonunun Özel Yeri
main() fonksiyonu C++ programının giriş noktasıdır (entry point). İşletim sistemi programını çalıştırdığında ilk çağrılan fonksiyon budur.
int main() {
// Program buradan başlar
return 0; // 0 = başarılı çıkış
}main() Hakkında Kurallar
Her C++ programında bir ve yalnız bir
main()olmalıDönüş tipi her zaman `int`
return 0başarılı çıkışı, sıfır olmayan değerler hatayı belirtirreturn 0;yazmasanız bile derleyici otomatik ekler (sadece main için geçerli)
main() ile Komut Satırı Argümanları
main() iki parametre alabilir:
#include <iostream>
using namespace std;
int main(int argc, char* argv[]) {
cout << "Argüman sayısı: " << argc << endl;
for (int i = 0; i < argc; i++) {
cout << "argv[" << i << "] = " << argv[i] << endl;
}
return 0;
}Programı ./program merhaba dunya şeklinde çalıştırırsan:
Argüman sayısı: 3
argv[0] = ./program
argv[1] = merhaba
argv[2] = dunyaargc— argüman sayısı (argument count)argv— argüman dizisi (argument vector), her eleman bir C-string
Parametresiz Fonksiyonlar
Fonksiyonların parametre alması zorunlu değil:
#include <iostream>
#include <ctime>
using namespace std;
int rastgeleSayi() {
return rand() % 100 + 1; // 1-100 arası
}
void simdikiZaman() {
time_t simdi = time(nullptr);
cout << "Şu an: " << ctime(&simdi);
}
int main() {
srand(time(nullptr));
cout << "Rastgele: " << rastgeleSayi() << endl;
simdikiZaman();
return 0;
}Parametresiz fonksiyonlar genellikle global durumu okur, sistem bilgisi döndürür veya sabit bir iş yapar.
Fonksiyonları Organize Etme
İyi bir programda her fonksiyonun tek bir sorumluluğu olmalı. Buna Single Responsibility Principle (tek sorumluluk ilkesi) denir.
#include <iostream>
#include <string>
using namespace std;
// KÖTÜ — tek fonksiyon her şeyi yapıyor
void herSeyiYap(string isim, int puan) {
// Giriş doğrulama
if (isim.empty()) { cout << "Hata!" << endl; return; }
if (puan < 0 || puan > 100) { cout << "Hata!" << endl; return; }
// Not hesaplama
string not_harf;
if (puan >= 90) not_harf = "A";
else if (puan >= 80) not_harf = "B";
else not_harf = "C";
// Yazdırma
cout << isim << ": " << not_harf << endl;
}
// İYİ — her fonksiyonun tek görevi var
bool gecerliMi(const string& isim, int puan) {
return !isim.empty() && puan >= 0 && puan <= 100;
}
string notHesapla(int puan) {
if (puan >= 90) return "A";
if (puan >= 80) return "B";
return "C";
}
void sonucYazdir(const string& isim, const string& not_harf) {
cout << isim << ": " << not_harf << endl;
}
int main() {
string isim = "Ali";
int puan = 85;
if (gecerliMi(isim, puan)) {
string not_harf = notHesapla(puan);
sonucYazdir(isim, not_harf);
}
return 0;
}İkinci yaklaşımda her fonksiyon küçük, test edilebilir ve yeniden kullanılabilir.
💡 İpucu: Bir fonksiyon 20-30 satırdan uzunsa, muhtemelen birden fazla iş yapıyordur. Parçalara bölmeyi düşün. Fonksiyon ismi "ve" içeriyorsa (
hesaplaVeYazdir) bu genellikle iki ayrı fonksiyon olması gerektiğinin işaretidir.
Fonksiyon İsimlendirme Kuralları
İyi fonksiyon isimleri kodun okunabilirliğini dramatik şekilde artırır:
Fiil ile başla:
hesapla,bul,kontrolEt,yazdirNe yaptığını anlat:
daireAlaniHesapla(),kullaniciDogrula()Kısa ama açık:
calc()yerinehesaplaVergi()Bool döndürenler:
mi/musorusu sor —gecerliMi(),bosalanMi(),hazirMi()camelCase veya snake_case: Projede tutarlı ol
// İYİ isimler
double hesaplaKDV(double fiyat);
bool stokVarMi(int urunId);
void raporOlustur();
string formatlaParaBirimi(double miktar);
// KÖTÜ isimler
double f(double x); // Ne yaptığı belirsiz
void islem(); // Hangi işlem?
int abc(int n); // AnlamsızÖzet
Fonksiyon belirli bir görevi paketleyen isimlendirilmiş kod bloğudur —
dönüşTipi isim(parametreler) { gövde }void fonksiyonlar değer döndürmez — yan etki üreten işler için kullanılır
return fonksiyonu sonlandırır ve değer döndürür — void olmayan fonksiyonlarda her code path'te return olmalı
Prototip (declaration) fonksiyonun imzasını bildirir — tanım (definition) gövdeyi içerir, büyük projelerde ikisi ayrı dosyalarda olur
main() programın giriş noktasıdır — dönüş tipi int, return 0 başarılı çıkış anlamına gelir
Her fonksiyon tek bir sorumluluk taşımalı — küçük, odaklı, iyi isimlendirilmiş fonksiyonlar yazılabilir kod üretir
AI Asistan
Sorularını yanıtlamaya hazır