Title: Nesneye Dayali Programlama
1Nesneye Dayali Programlama
2Türemis Siniflarda Bilinirlik Alani
- Bilinirlik alani (scope) bir ismin derleyici
tarafindan taninabildigi program araligidir. C ve
C da bir blok içinde ayni isimli birden fazla
degisken biliniyorsa o blok içinde ayni isimli
degisken kullanildiginda dar bilinirlik alanina
sahip olana erisilir. - Dar bilinirlik alanindaki isim kendisini kapsayan
daha genis bilinirlik alaninda bulunan ismi
maskeler.Onun görülmesini engeller. - Ayni kural C da türetme islemlerini kapsayacak
biçimde geçerlidir.
3- Önce su soruyu soralim Türetme durumunda taban
sinif türemis sinif tarafindan erisilebildigine
göre taban siniftaki bir isim mi daha dar
bilinirlik alanina sahiptir, türemis siniftaki
bir isim mi? - Cevap Türemis siniftaki isim. Çünkü taban
siniftaki isimler hem kendi sinifi içinde hem de
türemis sinif içinde kullanildigina göre daha
genis bir bilinirlik alanina sahiptir.
4Örnek
class Base protected int b public Base()b(0) void display()const include ltiostreamgt void Basedisplay()const stdcout ltlt "b " ltlt b ltlt stdendl class Der public Base int b public Der()b(1) void set(int) void display() const void func() const void Derset(int val) b val //Derb val void Derdisplay()const stdcout ltlt "b " ltlt b ltlt stdendl void Derfunc()const display()
5- Burada Der sinifinin set üye islevi içinde
kullanilan b ismi, daha dar bilinirlik alanina
sahip olan Der sinifinin b isimli elemanina
iliskindir. - Der sinifinin b isimli elemani Base sinifinin b
isimli elemanini maskeler yani görünmesini
engeller.(Tabii eger Der sinifinin b isimli bir
elemani olmasaydi burada kullanilan b, Base
sinifina iliskin olurdu.)
6- Ayrica Base sinifinin display üye islevi içinde
kullanilan b elemani Base sinifina iliskin
olandir. Zaten taban sinif türemis sinifa
erisemedigine göre hiçbir biçimde bunun Base
sinifina iliskin olmasi söz konusu degildir. - Türemis sinif içinde ayni isimli taban sinif
elemanlarina ve islevlerine çözünürlük isleci ile
erisilebilir.
7- Örnegin bu kez Der sinifinin iki parametreli set
isimli bir üye islevi daha oldugunu düsünelim - Islevde dogrudan kullanilan b, bilinirlik alani
kurallarina göre Der sinifina iliskin olandir.
Ancak çözünürlük isleci ile, yani Baseb ifadesi
ile kullanilan b, Base sinifina iliskin olandir. - Iki terimli çözünürlük islecini taban ve türemis
siniflarda ayni isimli elemanlar ya da islevler
varken taban sinifin elemanlarina erismek
amaciyla bu biçimde kullanilabilir.
void Derset(int x, int y) b x Baseb y
8- Bilinirlik alani kurallari islev isimleri için de
geçerlidir. Türemis ve taban sinifta ayni isimli
islevler varsa dar bilinirlik alani kuralina göre
türemis siniftaki anlasilir. - Örnegin Der sinifinin func islevi içinde çagrilan
display islevi Der sinifina ilskin olandir. - Çözünürlük isleci, ayni amaçla üye islevler için
de kullanilabilir.
9- Örnegin türemis sinif olan Der sinifinin func
isimli üye islevi içinde bu kez taban sinifin
display isimli islevi çagrilmak istenseydi bu
asagidaki gibi yapilabilirdi - Dar bilinirlik alani kurali disaridan sinif
elemanlarina erisirken de geçerlidir. Yukarida
verdigimiz türetme islemi için asagidaki kod
yazilmis olsun
void Derfunc() Basedisplay()
10int main() Der der_object, der_ptr der_object.display() //1 der_object.Basedisplay() //2 der_ptr der_object der_ptr-gtdisplay() //3 der_ptr-gtBasedisplay() //4 Base base_object base_object.display() //5 return 0
- Yukaridaki main islevinde yorum satirlariyla
isaretlenen islev çagrilarina bakalim - //1 Der sinifinin display islevi çagrilir.
- //2 Base sinifinin display islevi çagrilir.
- //3 Der sinifinin display islevi çagrilir.
- //4 Base sinifinin display islevi çagrilir.
- //5 Base sinifinin display islevi çagrilir. Taban
sinif türemis sinifa erisemez!
11- Bilinirlik alani ile erisilebilirlik ayni seyler
degildir. Cda her zaman önce isim aramasi daha
sonra erisim denetimi yapilir. Bu kuralin
etkisini yandaki gibi bir türetme isleminde
degerlendirelim
class Base public int x class Der public Base int x void func() Der der_object der_object.x 0 //Geçersiz!
12- C'a yeni baslayanlar func islevi içindeki
- der_object.x 0
- atamasinin geçerli olmasi gerektigini
düsünürler. - Hem türemis sinifta hem de taban sinifta x
isimli bir eleman olduguna göre, önce türemis
sinifta bulunan x isimli elemana erisilmeye
çalisilir. Türemis sinifta bulunan x sinifin
private bölümünde bulundugu için bu erisim
gerçeklesmez. Ancak taban sinifin public
bölümünde bulunan xe erisilir. - Ancak durum böyle degildir. Önce isim aramasi
yapilir. Türemis sinif olan Der sinifinin
bilinirlik alaninda x ismi bulundugunda isim
arama sona erdirilir. Aranan isim bulunmus ve x
isminin türemis sinif bilinirlik alanindaki x
oldugu anlasilmistir. Artik ne nedenle olursa
olsun yeniden bir isim aramasi yapilmaz. Simdi bu
x'e erisimin geçerli olup olmadigi sorgulanir.
Türemis sinifin x isimli elemani türemis sinifin
private bölümünde oldugu için erisim geçersizdir.
13Türemis Sinif Içinde Yapilan using Bildirimi
- Türemis ve taban siniflarin farkli bilinirlik
alani olusturduklarini biliyorsunuz. Türemis
sinif bilinirlik alani içinde bildirilen bir
isim, taban sinif içinde de kullanilmissa, taban
siniftaki isim maskelenir. - Maskelenme istenmiyorsa türemis sinif içinde
using bildirimi yapilabilir. Sinif içi using
bildirimiyle taban siniflara iliskin maskelenen
isimler görünür kilinir.
14- Böylece taban sinif ve türemis sinif islevleri
farkli bilinirlik alaninda olsalar bile
yüklenebilir. - Yandaki kodu inceleyelim
include ltiostreamgt class Base public void foo()stdcout ltlt "Basefoo()" ltlt stdendl class Der public Base public using Basefoo void foo(int)stdcout ltlt "Derfoo(int)" ltlt stdendl int main() Der der_object der_object.foo() der_object.foo(25) return 0
15- Der sinifinin tanimi içinde yapilan using
bildirimiyle Base sinifinin foo isimli islevi Der
sinifi içinde görülebilir hale getiriliyor.
Böylece - der_object.foo()
- çagrisi söz konusu oldugunda
- void Basefoo()
- islevi de çagriya aday islev olarak
belirlenir. using bildirimiyle taban ve türemis
sinifin foo islevleri ayri bilinirlik alanlarina
ait olmasalar da yüklenebilir.
16- Simdi de asagidaki koda bakalim
- main islevi içinde çagrilan, Der sinifinin foo
islevidir. Der sinifinin foo islevinin gizli
parametre degiskeni Der türünden iken, Base
sinifinin foo islevinin gizli parametre degiskeni
Base türündendir.
include ltiostreamgt class Base public void foo()stdcout ltlt "Basefoo()" ltlt stdendl class Der public Base public using Basefoo void foo()stdcout ltlt "Derfoo()" ltlt stdendl int main() Der der_object der_object.foo() return 0
17Erisilebirligin Tekrar Tanimlanmasi
- Taban sinifinin public üyelerinin
erisilebilirligi türemis sinif içerisinde yeniden
tanimlanabilir. - Private olarak miras alirsaniz, taban sinifin
bütün public üyeleri private olur.Bunlardan
herhangi birinin görülebilir olmasini isterseniz,
türemis sinifin public kisminda sadece
isimlerinin basina using kelimesini kullanmaniz
yeterli.
18- 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 Basef // f() is public again , i is
still private - void fb1()
-
- int main()
- Base b
- Derived d
- b.i5 // OK public in Base
- d.i0 // ERROR private inheritance
- b.f() // OK
19Atama operatörü ve miras
- Taban sinifin atama operatörü, türemis sinifin
atama operatörü olamaz. - Örnek
- class String
- protected
- int size
- char contents
- public
- const String operator(const String )
// assignment operator // Other methods -
- const String Stringoperator(const String
in_object) -
- size in_object.size
- delete contents // delete old contents
- contents new charsize1
- strcpy(contents, in_object.contents)
- return this
-
20- String2 sinifi String sinifindan türemistir.Eger
atama operatörü gerekliyse su sekilde
yazilmalidir. - 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 String2operator(const
String2 in_object) -
- size in_object.size // inherited size
- delete contents
- contents new charsize 1 // inherited
contents - strcpy(contents, in_object.contents)
- size2 in_object.size2
- delete contents2
- contents2 new charsize2 1
21- Bir önceki örnekte, String(taban) sinifin
verileri protected olmalidir. Aksi halde
String2(türemis) sinifin metodlari onlara
erisemez.String2 sinifi için atama operatörü
yazmanin en iyi yolu, String(taban) sinifin atama
operatörünü çagirmaktir. - // Assignment operator
- const String2 String2operator(const String2
in_object) -
- Stringoperator(in_object) // call the
operator of String (Base) - coutltlt "Assignment operator of String2 has been
invoked" ltlt endl - size2 in_object.size2
- delete contents2
- contents2 new charsize2 1
- strcpy(contents2, in_object.contents2)
- return this
-
22Çoklu Türetme (multiple inherritence)
- Bir sinifin birden fazla taban sinifa sahip
olmasi durumudur. Çoklu türetme durumunda
baslangiç fonksiyonlarinin çagrilmasi bildirimde
ilk yazilan taban sinifin baslangiç fonksiyonu
önce çagrilacak biçimdedir. - Örnegin class Cpublic A, public B böyle bir
bildirimde önce a, b, c seklinde baslangiç
fonksiyonlari çagrilir. Bitis fonksiyonlarida c,
b, a olacak sekilde tam tersdir.
23- Türemis sinif nesnesi bütün taban sinif
nesnelerinide içerir. Taban sinif nesnelerinin
tüenmis sinif içindeki organizasyonu standart
olarak belirlenmemistir. Ancak bildirimde
genllikle bildirimde ilk yazilan taban sinifin
veri elemanlari düsük anlamli adreste oacak
biçimde ardisil bir yerlesim söz konusudur.
24(No Transcript)
25Tekrarli Taban Siniflar
- class Gparent
-
- class Mother public Gparent
-
- class Father public Gparent
-
- class Child public Mother, public Father
-
26- Mother ve Father siniflarinin ikiside Gparent
sinifindan türemistir, ve Child sinifi Mother ve
Father siniflarindan türemistir.Hatirlayalim ki,
her bir nesne miras yoluyla, taban sinifin
altnesnesini içererek yaratilir. Mother nesnesi
ve Father nesnesi Gparentin alt nesnelerini,
Child nesnesi Mother and Fatherin alt
nesnelerini, dolayisiyla Child nesnesi biri
Motherdan biri Fatherdan türemis, Gparentin iki
alt nesnesini içerir
27- class Gparent
-
- protected
- int gdata
-
- Childdan su sekilde ulasmaya çalisirsaniz hata
verir. - class Child public Mother, public Father
-
- public
- void Cfunc()
-
- int temp gdata // ERROR ambiguous
-
-
28- Derleyici gdataya verilen referansin belirsiz
oldugunu söyliyecektir.Hangi çesit gdataya
ulasacagini bilemez, Gparentdan miras alan
Mother alt nesnesinden gelen gdata mi, yoksa
Gparentdan miras alan Father alt nesnesinden
gelen gdatami.
29Sanal Taban Siniflar
- Virtual kelimesi kullanarak olusturulur. Örnegin
Mother ve Father Gparentdan 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üremis siniflar içinden sadece bir tanesinin alt
nesnesinin miras alinmasini söyler. Bu
belirsizlik problemini çözer.