290 likes | 520 Views
Nesneye Dayal ı Programlama. DERS 6. Türemiş Sınıflarda Bilinirlik Alanı.
E N D
Nesneye Dayalı Programlama DERS 6 Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli
Türemiş Sınıflarda Bilinirlik Alanı • Bilinirlik alanı (scope) bir ismin derleyici tarafından tanınabildiği program aralığıdır. C veC++ da bir blok içinde aynı isimli birden fazla değişken biliniyorsa o blok içinde aynı isimlideğişken kullanıldığında dar bilinirlik alanına sahip olana erişilir. • Dar bilinirlikalanındaki isim kendisini kapsayan daha geniş bilinirlik alanında bulunan ismi maskeler.Onun görülmesini engeller. • Aynı kural C++’ da türetme işlemlerini kapsayacak biçimdegeçerlidir. Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli
Önce şu soruyu soralım: Türetme durumunda taban sınıf türemiş sınıftarafından erişilebildiğine göre taban sınıftaki bir isim mi daha dar bilinirlik alanınasahiptir, türemiş sınıftaki bir isim mi? Cevap: Türemiş sınıftaki isim. Çünkü tabansınıftaki isimler hem kendi sınıfı içinde hem de türemiş sınıf içinde kullanıldığına göredaha geniş bir bilinirlik alanına sahiptir. Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli
Örnek: Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli
Burada Der sınıfının set üye işlevi içinde kullanılan b ismi, daha dar bilinirlik alanına sahip olan Der sınıfının b isimli elemanına ilişkindir. • Der sınıfının b isimli elemanı Base sınıfının b isimli elemanını maskeler yani görünmesini engeller.(Tabii eğer Der sınıfının b isimli bir elemanı olmasaydı burada kullanılan b, Base sınıfına ilişkin olurdu.) Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli
Ayrıca Base sınıfının display üye işlevi içinde kullanılan b elemanı Base sınıfına ilişkin olandır. Zaten taban sınıf türemiş sınıfa erişemediğine göre hiçbir biçimde bunun Base sınıfına ilişkin olması söz konusu değildir. • Türemiş sınıf içinde aynı isimli taban sınıf elemanlarına ve işlevlerine çözünürlük işleci ile erişilebilir. Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli
Örneğin bu kez Der sınıfının iki parametreli set isimli bir üye işlevi daha olduğunu düşünelim: • İşlevde doğrudan kullanılan b, bilinirlik alanı kurallarına göre Der sınıfına ilişkin olandır. Ancak çözünürlük işleci ile, yani Base::b ifadesi ile kullanılan b, Base sınıfına ilişkin olandır. • İki terimli çözünürlük işlecini taban ve türemiş sınıflarda aynı isimli elemanlar ya da işlevler varken taban sınıfın elemanlarına erişmek amacıyla bu biçimde kullanılabilir. Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli
Bilinirlik alanı kuralları işlev isimleri için de geçerlidir. Türemiş ve taban sınıfta aynı isimli işlevler varsa dar bilinirlik alanı kuralına göre türemiş sınıftaki anlaşılır. • Örneğin Der sınıfının func işlevi içinde çağrılan display işlevi Der sınıfına ilşkin olandır. • Çözünürlük işleci, aynı amaçla üye işlevler için de kullanılabilir. Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli
Örneğin türemiş sınıf olan Der sınıfının func isimli üye işlevi içinde bu kez taban sınıfın display isimli işlevi çağrılmak istenseydi bu aşağıdaki gibi yapılabilirdi: • Dar bilinirlik alanı kuralı dışarıdan sınıf elemanlarına erişirken de geçerlidir. Yukarıda verdiğimiz türetme işlemi için aşağıdaki kod yazılmış olsun: Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli
Yukarıdaki main işlevinde yorum satırlarıyla işaretlenen işlev çağrılarına bakalım: //1 Der sınıfının display işlevi çağrılır. //2 Base sınıfının display işlevi çağrılır. //3 Der sınıfının display işlevi çağrılır. //4 Base sınıfının display işlevi çağrılır. //5 Base sınıfının display işlevi çağrılır. Taban sınıf türemiş sınıfa erişemez! Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli
Bilinirlik alanı ile erişilebilirlik aynı şeyler değildir. C++’da her zaman önce isim araması daha sonra erişim denetimi yapılır. Bu kuralın etkisini yandaki gibi bir türetme işleminde değerlendirelim: Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli
C++'a yeni başlayanlar func işlevi içindeki der_object.x = 0; atamasının geçerli olması gerektiğini düşünürler. • “Hem türemiş sınıfta hem de taban sınıfta x isimli bir eleman olduğuna göre, önce türemiş sınıfta bulunan x isimli elemana erişilmeye çalışılır. Türemiş sınıfta bulunan x sınıfın private bölümünde bulunduğu için bu erişim gerçekleşmez. Ancak taban sınıfın public bölümünde bulunan x’e erişilir. • Ancak durum böyle değildir. Önce isim araması yapılır. Türemiş sınıf olan Der sınıfının bilinirlik alanında x ismi bulunduğunda isim arama sona erdirilir. Aranan isim bulunmuş ve x isminin türemiş sınıf bilinirlik alanındaki x olduğu anlaşılmıştır. Artık ne nedenle olursa olsun yeniden bir isim araması yapılmaz. Şimdi bu x'e erişimin geçerli olup olmadığı sorgulanır. Türemiş sınıfın x isimli elemanı türemiş sınıfın private bölümünde olduğu için erişim geçersizdir. Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli
Türemiş Sınıf İçinde Yapılan using Bildirimi • Türemiş ve taban sınıfların farklı bilinirlik alanı oluşturduklarını biliyorsunuz. Türemiş sınıfbilinirlik alanı içinde bildirilen bir isim, taban sınıf içinde de kullanılmışsa, taban sınıftakiisim maskelenir. • Maskelenme istenmiyorsa türemiş sınıf içinde using bildirimi yapılabilir.Sınıf içi using bildirimiyle taban sınıflara ilişkin maskelenen isimler görünür kılınır. Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli
Böylecetaban sınıf ve türemiş sınıf işlevleri farklı bilinirlik alanında olsalar bile yüklenebilir. • Yandaki kodu inceleyelim: Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli
Der sınıfının tanımı içinde yapılan using bildirimiyle Base sınıfının foo isimli işlevi Der sınıfıiçinde görülebilir hale getiriliyor. Böylece: der_object.foo(); çağrısı söz konusu olduğunda void Base::foo(); işlevi de çağrıya aday işlev olarak belirlenir. using bildirimiyle taban ve türemiş sınıfın fooişlevleri ayrı bilinirlik alanlarına ait olmasalar da yüklenebilir. Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli
Şimdi de aşağıdaki koda bakalım: • main işlevi içinde çağrılan, Der sınıfının foo işlevidir. Der sınıfının foo işlevinin gizliparametre değişkeni Der & türünden iken, Base sınıfının foo işlevinin gizliparametredeğişkeni Base & türündendir. Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli
Erişilebirliğin Tekrar Tanımlanması • Taban sınıfının public üyelerinin erişilebilirliği türemiş sınıf içerisinde yeniden tanımlanabilir. • Private olarak miras alırsanız, taban sınıfın bütün public üyeleri private olur.Bunlardan herhangi birinin görülebilir olmasını isterseniz, türemiş sınıfın public kısmında sadece isimlerinin başına using kelimesini kullanmanız yeterli. Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli
class Base{ private: int k; public: int i; void f(); }; class Derived : private Base{ // All members of Base are private now int m; public: using Base::f; // f() is public again , i is still private void fb1(); }; int main(){ Base b; Derived d; b.i=5; // OK public in Base d.i=0; // ERROR private inheritance b.f(); // OK d.f(); // OK return 0; }; Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli
Atama operatörü ve miras • Taban sınıfın atama operatörü, türemiş sınıfın atama operatörü olamaz. Örnek: class String{ protected: int size; char *contents; public: const String & operator=(const String &); // assignment operator: // Other methods }; const String & String::operator=(const String &in_object) { size = in_object.size; delete[ ] contents; // delete old contents contents = new char[size+1]; strcpy(contents, in_object.contents); return *this; } Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli
String2 sınıfı String sınıfından türemiştir.Eğer atama operatörü gerekliyse şu şekilde yazılmalıdır. class String2 : public String{ // String2 is derived from String int size2; char *contents2; public: const String2 & operator=(const String2 &); // assignment operator for String2 : // Other methods }; // **** Assignment operator for String2 **** const String2 & String2::operator=(const String2 &in_object) { size = in_object.size; // inherited size delete[ ] contents; contents = new char[size + 1]; // inherited contents strcpy(contents, in_object.contents); size2 = in_object.size2; delete[ ] contents2; contents2 = new char[size2 + 1]; strcpy(contents2, in_object.contents2); return *this; } Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli
Bir önceki örnekte, String(taban) sınıfın verileri protected olmalıdır. Aksi halde String2(türemiş) sınıfın metodları onlara erişemez.String2 sınıfı için atama operatörü yazmanın en iyi yolu, String(taban) sınıfın atama operatörünü çağırmaktır. //** Assignment operator ** const String2 & String2::operator=(const String2 & in_object) { String::operator=(in_object); // call the operator= of String (Base) cout<< "Assignment operator of String2 has been invoked" << endl; size2 = in_object.size2; delete[] contents2; contents2 = new char[size2 + 1]; strcpy(contents2, in_object.contents2); return *this; } Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli
Çoklu Türetme (multiple inherritence) • Bir sınıfın birden fazla taban sınıfa sahip olması durumudur. Çoklu türetme durumunda başlangıç fonksiyonlarının çağrılması bildirimde ilk yazılan taban sınıfın başlangıç fonksiyonu önce çağrılacak biçimdedir. • Örneğin class C:public A, public B { böyle bir bildirimde önce a, b, c şeklinde başlangıç fonksiyonları çağrılır. Bitiş fonksiyonlarıda c, b, a olacak şekilde tam tersdir. Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli
Türemiş sınıf nesnesi bütün taban sınıf nesnelerinide içerir. Taban sınıf nesnelerinin tüenmiş sınıf içindeki organizasyonu standart olarak belirlenmemiştir. Ancak bildirimde genllikle bildirimde ilk yazılan taban sınıfın veri elemanları düşük anlamlı adreste oacak biçimde ardışıl bir yerleşim söz konusudur. Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli
Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli
Tekrarlı Taban Sınıflar class Gparent { }; class Mother : public Gparent { }; class Father : public Gparent { }; class Child : public Mother, public Father { }; Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli
Mother ve Father sınıflarının ikiside Gparent sınıfından türemiştir, ve Child sınıfı Mother ve Father sınıflarından türemiştir.Hatırlayalım ki, her bir nesne miras yoluyla, taban sınıfın altnesnesini içererek yaratılır. Mother nesnesi ve Father nesnesi Gparent’in alt nesnelerini, Child nesnesi Mother and Father’ın alt nesnelerini, dolayısıyla Child nesnesi biri Mother’dan biri Father’dan türemiş, Gparentin iki alt nesnesini içerir Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli
class Gparent { protected: int gdata; }; Child’dan şu şekilde ulaşmaya çalışırsanız hata verir. class Child : public Mother, public Father { public: void Cfunc() { int temp = gdata; // ERROR: ambiguous } }; Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli
Derleyici gdata’ya verilen referansın belirsiz oldugunu söyliyecektir.Hangi çeşit gdata’ya ulaşacağını bilemez, Gparent’dan miras alan Mother alt nesnesinden gelen gdata mı, yoksa Gparent’dan miras alan Father alt nesnesinden gelen gdatamı. Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli
Sanal Taban Sınıflar • Virtual kelimesi kullanarak oluşturulur. Örneğin Mother ve Father Gparent’dan türeme yaparken: class Gparent { }; class Mother : virtual public Gparent { }; class Father : virtual public Gparent { }; class Child : public Mother, public Father { }; Virtual kelimesi compilera sonradan gelen türemiş sınıflar içinden sadece bir tanesinin alt nesnesinin miras alınmasını söyler. Bu belirsizlik problemini çözer. Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli