10.07.2015 Views

Sanal Fonksiyonlar ve Çokbiçimlilik - Trakya Üniversitesi

Sanal Fonksiyonlar ve Çokbiçimlilik - Trakya Üniversitesi

Sanal Fonksiyonlar ve Çokbiçimlilik - Trakya Üniversitesi

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

NESNEYE YÖNELİK PROGRAMLAMASANAL FONKSİYONLARVEÇOK BİÇİMLİLİKÖzlem AYDIN<strong>Trakya</strong> Üni<strong>ve</strong>rsitesiBilgisayar Mühendisliği BölümüNot: Bu sunumda Doç. Dr. Yılmaz KILIÇASLAN’ın Nesneye Yönelik Programlamadersi sunumlarından faydalanılmıştır.


SINIF HİYERARŞİSİ• Dört sınıf arasında tanımlamış olduğumuz kalıtım ilişkisişematik olarak aşağıdaki gibi gösterilebilir:CalisanUcretliCalisanYoneticiSatisElemanı


TEMEL VE TÜRETİLMİŞ SINIFLAR ARASINDA DÖNÜŞÜM - 2• Benzer şekilde, türetilmiş bir sınıf nesnesine işaret eden bir işaretçiörtük olarak bir temel sınıf nesnesine işaret eden bir işaretçiyedönüştürülebilir:Calisan *cPtr;UcretliCalisan isci( “Oya Kiper” );SatisElemani satici( “Ali Uzun” );Yonetici mudur( “Mehmet Demir “ );cPtr = &isci; //UcretliCalisan * => Calisan *cPtr = &satici; //SatisElemani * => Calisan *cPtr = &mudur; //Yonetici * => Calisan *


TEMEL VE TÜRETİLMİŞ SINIFLAR ARASINDA DÖNÜŞÜM - 3• Bir nesneye işaretçi ile referansta bulunulduğu zaman hangi elemanfonksiyonun çağrılacağını işaretçinin tipi belirler. Eğer bir türetilmiş sınıfnesnesine bir temel sınıf işaretçisi ile işaret ederseniz yalnızca temel sınıfa aitfonksiyonları çağırabilirsiniz:SatisElemani satici( “Ali Uzun” );SatisElemani *sPtr;UcretliCalisan *uPtr;sPtr = &satici;uPtr = &satici;uPtr->sureBelirle(40.0); //UcretliCalisansPtr->ucretBelirle(6.0); //UcretliCalisanuPtr->satislariBelirle(1000.0); //ErrorsPtr->satislariBelirle(1000.0); //SatisElemanisPtr->komisyonBelirle(0.05); //SatisElemanifloat taban, toplam;taban = uPtr->odemeHesapla(); //UcretliCalisantoplam = sPtr->odemeHesapla(); //SatisElemani


TEMEL VE TÜRETİLMİŞ SINIFLAR ARASINDA DÖNÜŞÜM - 4• Türetilmiş bir sınıf işaretçisinin bir temel sınıf işaretçisinedönüştürülebilmesi, örneğin, bir çalışanlar topluluğuoluşturmamıza imkan <strong>ve</strong>rebilir:class PersonelListesi{public:PersonelListesi();ekle( Calisan *yeniPer );// …};


8TEMEL VE TÜRETİLMİŞ SINIFLAR ARASINDA DÖNÜŞÜM - 5PersonelListesi bolum1;UcretliCalisan *ucretliPtr;SatisElemani *saticiPtr;Yonetici *yoneticiPtr;// Yeni nesneler için bellek talebiucretliPtr = new UcretliCalisan(“Ayse Suer” );saticiPtr = new SatisElemani( “Ali Demir” );yoneticiPtr = new Yonetici( “Mehmet Yilmaz” );// Listeye eklemebolum1.ekle( ucretliPtr );bolum1.ekle( saticiPtr );bolum1.ekle( yoneticiPtr );• Buradaki sorun her nesne yalnızca genel bir Calisan düzeyinde işleme tabiolabilir.


SANAL FONKSİYONLAR (sentaks)• <strong>Sanal</strong> fonksiyon temel bir sınıfta bildirimi yapılan fakat türetilmiş bir sınıftayeniden tanımlanmasını beklediğimiz bir eleman fonksiyondur.• Bir sanal fonksiyon bildirimi temel sınıftaki eleman fonksiyon bildirimininöncesine virtual anahtar sözcüğünü yerleştirerek gerçekleştirilir.• Global fonksiyonlar, arkadaş fonksiyonlar <strong>ve</strong> statik eleman fonksiyonlar sanalfonksiyon olamazlar.• virtual anahtar sözcüğü, türetilmiş sınıflardaki bildirimler ya da sınıfdışında tanımlanmış sanal fonksiyonlar için gerekli değildir; bir sanalfonksiyonun türetilmiş sınıflardaki <strong>ve</strong>rsiyonları örtük olarak sanalbildirimlidirler.• Türetilmiş sınıftaki sanal fonksiyon bildiriminde ya da sınıf dışındaki sanalfonksiyon tanımında virtual anahtar sözcüğünü kullanmak derleyicitarafından bir hata olarak yorumlanmaz.


SANAL FONKSİYONLAR (semantik)• “Normal” bir erişimde, sanal fonksiyonlar diğer bütün sınıfa aiteleman fonksiyonlar gibi davranırlar. Fakat, sanal fonksiyonlarıönemli kılan <strong>ve</strong> çalışma zamanlı çok biçimliliği desteklemesinisağlayan bir işaretçi ya da referans ile erişilmeleri halindekidavranışlarıdır.• Eğer bir temel sınıf işaretçisi ya da referansı bu temel sınıftantüretilmiş bir sınıfın nesnesine işaret ediyorsa / referanstabulunuyorsa, sıradan fonksiyonlarda olmasını beklediğimizin tersine,C++ sanal bir fonksiyonun hangi <strong>ve</strong>rsiyonunu çağıracağına nesneyebakarak karar <strong>ve</strong>rir.• Bu karar çalışma zamanında gerçekleştirilir.• Dolayısıyla, farklı nesnelere işaret edildiğinde / referanstabulunulduğunda fonksiyonun farklı <strong>ve</strong>rsiyonları çalıştırılacaktır.


SANAL FONKSİYONLAR (örnek)//<strong>Sanal</strong> odemeHesapla fonksiyonlu calisan sinif hiyerarsisiclass Calisan{ public:Calisan( const char *nm );char *isimSoyle() const;virtual float odemeHesapla() const;virtual ~Calisan() {}private:char isim[30]; };class UcretliCalisan : public Calisan{ public:UcretliCalisan( const char *nm );void ucretBelirle( float ucrt );void sureBelirle( float st );float odemeHesapla() const; // sanal (ortuk)private:float ucret;float saat; };


SANAL FONKSİYONLAR (örnek)class SatisElemani : public UcretliCalisan{ public:SatisElemani( const char *nm );void komisyonBelirle( float kom );void satislariBelirle( float satislar );float odemeHesapla() const; // sanal (ortuk)private:float komisyon;float satisMiktari; };class Yonetici : Calisan{ public:Yonetici( const char *nm );void maasBelirle( float maas );float odemeHesapla() const; // sanal (ortuk)private:float haftalikMaas; };


SANAL FONKSİYONLAR (örnek)• Her sınıfın kendisine ait odemeHesapla fonksiyonununtanımı değişmeden kalabilir. Fakat, temel sınıfa eklenenodemeHesapla fonksiyonu için bir tanım gerekmektedir:float Calisan::odemeHesapla() const{ cout


SANAL FONKSİYONLAR (örnek)• // Bir Calisan isaretcisi ile odemeHesapla cagrimiCalisan *cPtr;float ucret;cPtr = &isci;ucret = cPtr->odemeHesapla(); //UcretliCalisancPtr = &satici;ucret = cPtr->odemeHesapla(); //SatisElemanicPtr = &mudur;ucret = cPtr->odemeHesapla(); //YoneticiEğer odemeHesapla sanal bildirimli olmasaydı, herfonksiyon çağrımı, 0.0 değerini döndürenCalisan::odemeHesapla fonksiyonunu çalıştıracaktı.Fakat, <strong>ve</strong>rilen çağrımların aynı olmasına rağmençalıştırılacak fonksiyonlar farklı olacaktır.


SANAL FONKSİYONLAR (örnek)// Bir baska ornek#include using namespace std;class temel{ public:virtual void sanalFonk(){cout


SANAL FONKSİYONLAR (örnek)int main(){temel *p, b;turetilmis1 d1;turetilmis2 d2;p = &b;p->sanalFonk();p = &d1;p->sanalFonk();p = &d2;p->sanalFonk();}return 0;Program çıktısını belirleyiniz.


SANAL FONKSİYONLAR (örnek)• Program çıktısı:Temel sinif – sanalFonkTuretilmis sinif1 – sanalFonkTuretilmis sinif2 – sanalFonk• “Normal” yolla sanal fonksiyon çağrımı:d2.sanalFonk; // turetilmis2::sanalFonk


SANAL FONKSİYONLAR <strong>ve</strong> REFERANSLAR - 1// Temel sinif referansi ile sanal fonksiyon erisimi#include using namespace std;class temel{ public:virtual void sanalFonk(){cout


SANAL FONKSİYONLAR <strong>ve</strong> REFERANSLAR - 2// Temel sinif referansini parametre alan fonksiyonvoid f(temel &r){ r.sanalFonk() ; }int main(){temel b;turetilmis1 d1;turetilmis2 d2;f(b);f(d1);f(d2);}return 0;Program çıktısını belirleyiniz.


SANALLIK KALITIMLA AKTARILIR - 1• <strong>Sanal</strong> bir fonksiyon kalıtıldığında, sanal doğası da kalıtılır:#include using namespace std;class temel{ public:virtual void sanalFonk(){cout


SANALLIK KALITIMLA AKTARILIR - 2int main(){temel *p, b;turetilmis1 d1;turetilmis2 d2;p = &b;p->sanalFonk();p = &d1;p->sanalFonk();p = &d2;p->sanalFonk();}return 0;• Bu kez, turetilmis2 adlı sınıf temel adlı sınıftan değilturetilmis1 adlı sınıftan türetilmiştir ama sanalFonk yinesanal kalmıştır. Program çıktısını belirleyiniz.


SANAL FONKSİYONLAR HİYERARŞİKTİR - 1• Eğer türetilmiş bir sınıf sanal bir fonksiyonu yeniden tanımlamaz isebu sınıfın bir nesnesi sanal fonksiyona erişmek istediğinde temel sınıftarafından tanımlanan <strong>ve</strong>rsiyon kullanılır:#include using namespace std;class temel{ public:virtual void sanalFonk(){cout


SANAL FONKSİYONLAR HİYERARŞİKTİR - 2int main(){temel *p, b;turetilmis1 d1;turetilmis2 d2;p = &b;p->sanalFonk();p = &d1;p->sanalFonk();p = &d2;p->sanalFonk();}return 0;Program çıktısını belirleyiniz.


SANAL FONKSİYONLAR HİYERARŞİKTİR - 3• Program çıktısı:Temel sinif – sanalFonkTuretilmis sinif1 – sanalFonkTemel sinif – sanalFonk• Yukarıdaki program genel bir kuralın özel bir durumunuörneklemektedir. Kalıtım, C++’da hiyerarşik olarak tanımlandığıiçin, sanal fonksiyonlar da hiyerarşik olmalıdır. Bu ise, eğertüretilmiş sınıf sanal fonksiyonu yeniden tanımlamış ise tersindenhiyerarşik sıralamada ilk yeniden tanımlanmış fonksiyonunkullanılacağı anlamına gelir (bkz. bir sonraki örnek).


SANAL FONKSİYONLAR HİYERARŞİKTİR - 4#include using namespace std;class temel{ public:virtual void sanalFonk(){cout


SANAL FONKSİYONLAR HİYERARŞİKTİR - 5int main(){temel *p, b;turetilmis1 d1;turetilmis2 d2;p = &b;p->sanalFonk();p = &d1;p->sanalFonk();p = &d2;p->sanalFonk();}return 0;Program çıktısını belirleyiniz.


SANAL FONKSİYONLAR HİYERARŞİKTİR - 6• Program çıktısı:Temel sinif – sanalFonkTuretilmis sinif1 – sanalFonkTuretilmis sinif1 – sanalFonk


SAF SANAL FONKSİYONLAR - 1• Birçok durumda temel sınıftaki sanal fonksiyon için anlamlı birtanım bulunmayabilir. Bu durumlarda saf sanal fonksiyonlar (“purevirtual functions”) kullanılır.• Saf sanal fonksiyon temel sınıfta tanımı olmayan sanalfonksiyondur <strong>ve</strong> bildiriminin genel formu aşağıdaki gibidir:virtual tip fonksiyon-ismi(parametreler) = 0;• Saf sanal fonksiyon türetilmiş bütün sınıflarda yenidentanımlanmalıdır. Aksi, derleyici-zamanlı hataya yol açar.• En az bir saf sanal fonksiyon içeren sınıfa soyut (“abstract”) sınıfdenir.• Soyut sınıflara ait nesne yaratılamaz ama soyut sınıflara işaret edenişaretçiler ya da referansta bulunan referanslar yaratılabilir.


SAF SANAL FONKSİYONLAR - 2#include using namespace std;class sayi{ protected:int deger;public:void degerBelirle(int i) { deger = i;}virtual void goruntule() = 0; // saf sanal fonksiyon bildirimi};class hexTip : public sayi{ public:void goruntule() {cout


SAF SANAL FONKSİYONLAR - 3int main(){desTip d;hexTip h;oktTip o;d.degerBelirle(20);d.goruntule(); // 20h.degerBelirle(20);h.goruntule(); // 14o.degerBelirle(20);o.goruntule(); // 24}return 0;


SANAL YIKICI FONKSİYONLAR• Problem: Dinamik olarak yaratılmış nesneleri delete operatörü ileyok etmek potansiyel bir problem kaynağıdır. Eğer delete birtemel sınıf işaretçisine uygulanıyorsa, işaretçi türetilmiş bir sınıfınnesnesini işaret ediyor bile olsa, derleyici temel sınıfın yıkıcıfonksiyonunu çağıracaktır.• Çözüm: Bu sorun temel sınıfın yıkıcı fonksiyonunu sanal yaparakçözülür. Bu şeklide, türetilmiş sınıfların yıkıcı fonksiyonları da sanalyapılmış olacaktır <strong>ve</strong> böylelikle delete operatörü temel sınıfişaretçisine uygulandığında ilgili yıkıcı fonksiyon çağrılacaktır.• İlke olarak sanal fonksiyon içeren bir sınıf yazıldığında, sanal biryıkıcı fonksiyon da tanımlanmalıdır.• Yıkıcı fonksiyonların aksine, yapıcı fonksiyonlar sanal olaraktanımlanamaz.

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!