C++ Function Overloading & Function Overloading Resolution
4 min readDec 5, 2018
- Konu içerisinde function overloading ve resolution mekanizmalarına değineceğiz. Derleyicinin arka planda bunu nasıl yaptığını, hangi aşamalardan geçtiğini anlatmaya çalışacağım.
- Fonksiyonların aşırı yüklenmesi çevirisi yanlış bir anlama çıkabiliyor. Aşırı olan birşey iyi değildir. Burada fonksiyonların yüklenmesi diyelim.
- C++ dilinde bu mekanizma var, C dilinde yok.
- Function overloading basit olarak aynı isimli fonksiyonların bir arada bulunmasıdır.
- Amaç: Client’ın işini kolaylaştırmak.
C dilinde bu mekanizmanın olmaması ne gibi sıkıntılar çıkarıyor ve neden yok?
- C dilinde böyle bir yapının olmamasından dolayı şöyle sıkıntılar çıkmıştır. Her fonksiyon için ayrı bir isim oluyor. Örneğin mutlak değer fonksiyonu abs(), floating-point number için fabs(), long int için labs().. işte böyle bir sıkıntı söz konusu.
- C dilinde olmamasının sebebi derleyicinin kodunu küçük tutmak. Çünkü böyle bir yapıda derleyecinin kodu çok daha fazla büyüyecek. Bu karmaşık derleyici yoran bir mekanizma. Derleyicisi en az %30 kadar büyütürdü.
- Runtime maliyeti yok, çünkü ne kadar aynı isimli fonksiyon olsa da hangi fonksiyonun çağırıldığı, derleyici compile time da anlıyor. Yani linker a dışsal referans olarak bunu anladıktan sonra yazıyor.
- Hangi fonksiyon çağrıldığı anlama, compile time da static binding yada early binding denir. Bind (ilişkilendirme, bağlama)
Dynamic binding | C++ OOP en önemli araçları
- Late binding | Çalışma zamanı çokbiçimliliği (Runtime Polymorphism)
Derleyicinin hangi fonksiyonu çağırdığını nasıl anlar?
- (Function Overload Resolution) derleyicinin dilin kurallarına dayanarak hangi fonksiyonu çağrıldığını anlama işine denir
- (Fonksiyon imzası) bildirimden tür çıkartım, geriye kaç parametre, kaç değişken var ve türleri neler gibi.
- İmza terimini duyduğunuzda, fonksiyon geri dönüş değerinin türü dahil değil.
- Bildirim dediğimizde fonksiyon geri dönüş değeri türü dahil.
Fonksiyon Overloading dendiğinde 3 koşulun olması gerekiyor.
1. Fonksiyon isimleri aynı olacak. 2. Scopeları aynı olucak (aynı scope larda fonksiyonlar birbirini overload eder, farklı scopelardaki fonksiyonlar birbirini maskeler) 3. İmzaları farklı olucak (parametre sayısı veya parametre turu)
- Aynı scope ta aynı isimli 2 fonksiyon varsa ve function overloading yoksa 2 şey olabilir, ya error yada redeclaration(yeniden bildirim)
- Function Overloading için distinct type olmalıdır.
- C++11 de typedef bildirimlerinin yerine uydurulan ayrı bir araç var.
- typedef isimleri distinct tür değildir, bu yüzden typedef isimleriyle function overload olmaz. C++11 de artık typedef bildirimlerinin yerine uydurulan ayrı bir araç var. “using Kerem int” gibi.
- using bildirimi, typedef te olmayan ilave anlamlarda var.
Asla pointer olmayan bir parametreyi const yapmayın. Yaparsak ne olur?
- Fonksiyon bildirimi var yada yok. Derleyici burada ki const anahtar sözcüğünü ciddiye almaz.
- Neden ciddiye almaz? Çünkü bu call by value bir anlam yüklersek, x değerini değiştiremem der ve sen onu değiştirsende değiştirmesende benim değişkenime olan birşey yok. O yüzden beni ilgilendirmiyor der.
- pointer olmayan parametreleri bildirimde veya tanımda const yapmayın onun bir anlamı yok.
- derleyici bunu görmez
- Eğer 2 parametre türleri aynı ise pointer değilse ve biri T türünden ise öteki const T türündense function overloading değil, errorde değil, redeclaration’dır. Bu cümle biraz karışık gelmiş olabilir. Örnek vererek acıklayalım.
Ufak tekrar (function overloading için olması gereken):
- Scope aynı olacak.
- İsimler aynı olacak.
- İmzalar farklı olacak.
- enum -> int türüne dönüşüm var.
- doğal türlerden -> enum türüne dönüşüm yok.
- Farklı türden pointerlar arası dönüşüm yok
T * -> void * a dönüşür
void * -> T * a dönüşmez
- Bir pointera tam sayı olarak 0 atarsanız tam sayı olan 0 null adresine dönüşür.
FUNCTION OVERLOAD RESOLUTION
- Derleyicinin hangi fonksiyonu çağrıldığını anlama mekanizmasıdır.
- İki şekilde sonuçlabilir. (ERROR yada LEGAL)
- Yani ortada bir function overloading var diye yapılan her çağrı doğru olmayabilir.
- Error ise 2 seçenek var,
- Yanlış function çağrılması(no match),
- Ambiguity (Çift anlamlılık hatası)
- Aday fonksiyonlar,
- İlk aşamada sadece aynı isimde olmaları yeterli. Aynı scope içinde olucak. Farklı scope içinde ise maskeleme olur.
- İkinci aşamada derleyici uygun fonksiyonları bulmak ister. Bu aşamada hiç uygun fonksiyon bulamassa ERROR olur. Burada ki aşama uygun fonksiyonları bulup eleme yapma.
- Birden fazla uygun fonksiyon varsa, derleyici dilin kurallarına göre argümanlardan parametre değişkenlerine yapılan dönüşümü belirli kalite grubuna ayıracak. Bunlara bir renk vericek gibi düşünebiliriz. Yani her argümandan her parametre değişkenine dönüşümün kalitesi aynı değil. Eğer fonksiyon çağrısındaki argümanın diyelim ki birinci fonksiyona dönüşümü A kalitesinde ise ikinci fonksiyonun ilgili parametresine dönüşümü ondan daha düşük B kalitesinde ise A seçilecektir.
Yani bu aşama da derleyici fonksiyonları derecelendirecek. Bu derecelendirmeyi neye göre yapıyor?
- Bir argümandan bir parametre değişkenine legal olarak atama yapılabiliyorsa dönüşümün kalitesi 4 kalite gurubundan biri olacaktır. (Yüksek kaliteden -> Düşük kaliteye)
1. EXACT MATCH (Tam Uyum)
2. PROMOTION (Terfi — Yükseltme)
3. STANDARD CONVERSION (Standard Dönüşüm)
4. USER DEFINED CONVERSION
- Bir argüman bir parametre değişkenine değer atanırken, derleyici function overloading seçimi yaparken rank vericek, derecelendirecek
- İkiside aynı ranka sahip ise bu ambiguity(en çok 3. ve 4. case için ambiguity oluyor)
EXACT MATCH
- Exact match tam uyumluluk olarak çevirebiliriz. Örneğin int argümanı int parametreye göndermek, float’u float’a göndermek exact matchtir.
- Bazı özel durumlarda exact match kabul edilir,
- Eğer fonksiyon parametresi const T ise bu fonksiyonu T ile çağırırsak T dan const a dönüşüm exact match kabul edilir.
- func(int x); int y = 10; func(y); // sol taraf değerinden sağ taraf dönüşüm exact math l value ~> r value translation.
- dizi isimlerini sizeof() operatörü ptr gönderilmesi sonucunda dizinin ilk elemanı adrese dönüştürülüyor.
PROMOTION
- int altı türlerin, int’e yükseltilmesi(c dilinde var)(integral promotion)
- int altı türler(short, char, bool) int’e yükseltilmesi (Yeni gelen char türleri hariç.)
- float türünden double dönüşümde promotion
- Dikkat double türünden long double’a vs dönüşümleri promotion değil
- int türünden unsigned int ve int türünden double dönüşümleri promotion değil
STANDARD CONVERSION
- Argümandan parametre dönüşümü legal ama exact match ve promotion değil ise o zaman standard conversion’dır.
- Örnek int türünden double atama legal
- unsigned int türünden int türüne standard conversion
- 0’dan pointer’a standard conversion
USER DEFINED CONVERSİON
- C dilinde olan birşey değil ama C++ dilinde var.
- User define conversion, programcı tarafından oluşturulan tanımlanan dönüşümlerdir.
- Bir dönüşüm, biz fonksiyon yazdık diye yapılıyorsa buna user defined conversion denir. O fonksiyon yazılmasaydı legal olmayacaktı.