C++ Dersi: Nesne Tabanlı Programlama Bölüm 11: Bileşim, Arkadaş ve Diğer Araçlar
İçerik Bileşim Arkadaş Fonksiyonlar ve Sınıflar Arkadaş Fonksiyonlar Arkadaş Sınıflar Sabit Nesneler Sabit Üye Fonksiyonlar Dinamik Bellek Kullanımı this Göstergesi Statik Sınıf Üyeleri Özel Başlık Dosyası #ifndef, #ifdef ve #endif Önişlemci Komutları 2
Sınıflar Arası İlişki İki sınıfın arasında dört tip ilişki olabilir. Sınıflar birbirlerinden bağımsız tanımlanabilir, Sınıflar arkadaş (friend) olarak tanımlanabilir, Sınıflar miras yoluyla ilişkilendirilebilir, Sınıflar bileşim yoluyla bağlanabilirler. 3
İng. Composition Bileşim Bir sınıf üyesinin başka bir nesne olması durumudur. Bir nesnenin içinde başka bir nesne yer alır. Başka bir nesne 4
#include <iostream> #include <string> using namespace std; class Tarih ; int gun,ay,yil; Tarih(int g,int a,int y):gun(g),ay(a),yil(y) void Tarih::yaz(); void Tarih::yaz() cout<<gun<<"/"<<ay<<"/"<<yil<<endl; class Birey ; string isim; Tarih dogumgunu; Birey(string,int,int,int); void yaz(); void Birey::yaz() cout<<isim<<" "; dogumgunu.yaz(); Birey::Birey(string s,int g,int a,int y) :dogumgunu(g,a,y) isim=s; int main() Birey insan("tolga",17,1,1997); insan.yaz(); return 0; ÇIKTI Tolga 17/1/1997 dogumgunu isim insan gun ay yil Tolga 17 1 1997 5
İng. Friend Arkadaş Fonksiyonlar Sınıfın üyesi olmamasına rağmen o sınıfın private üyelerine erişme hakkına sahip fonksiyonlardır friend anahtar kelimesi ile fonksiyon prototipinde belirtilir 6
Örnek #include <iostream> using namespace std; class Dene ; int no; Dene (int n=0):no(n) friend void yaz(dene&); void yaz(dene &x) cout<< numara = <<x.no<<endl; int main() Dene test1(7),test2(12); yaz(test1); yaz(test2); return 0; Arkadaş fonksiyon prototipi Arkadaş fonksiyon tanımı. fonksiyonun tanımı yapılırken sınıf ismi ve ikili çözümleme operatörü (::) yazılmaz. Arkadaş fonksiyon çağırımı 7
Arkadaş Sınıflar Bir sınıf başka bir sınıfın arkadaşı olarak tanımlanırsa tüm private üyelerine erişebilme hakkına sahip olur. 8
Örnek #include <iostream.h> using namespace std; class B; class A int x; A(int _x):x(_x) friend class B; ; class B int y; Ön tanım Arkadaş sınıf tanımı void fon(a& nsn); ; void B::fon(A& nsn) y=nsn.x; cout<<"y="<<y<<endl; int main() A bir(10); B iki; iki.fon(bir); return 0; ÇIKTI y=10 Arkadaş sınıf olduğu için x üyesine erişir 9
İng. Constant object Sabit Nesne Yapıcı fonksiyon ile ilk atamalar yapıldıktan sonra üyelerin değerini değiştiremediğimiz nesnedir. 10
Örnek class Eleman int no; Eleman(int _no):no(_no)... ; int main() const Eleman kisi(123); kisi.no=333; return 0; Sabit nesne tanımı Sabit nesne olduğu için hata verir 11
Sabit Üye Fonksiyonlar const olarak tanımlanan sabit üye fonksiyonlar, sınıfa ait veri üyelerinin değerini değiştiremez. const komutu, üye fonksiyonun hem prototipinde hem de tanımlamasında yer alır. Programın okunulabilirliğini artırır. Programcı sabit üye fonksiyonlarının, veri üyelerinin değerini değiştirmeyeceğini, sabit olmayan üye fonksiyonlarının da veri üyelerinin değerini değiştirebileceğini düşünür. Sabit üye fonksiyon içerisinden başka bir sabit olmayan ve dolayısı ile veri üyelerinin değerini değiştirebilen üye fonksiyonun çağrılması, derleme zamanında hata üretir. 12
Örnek #include "Daire.h" #define PI 3.14 #include <iostream> using namespace std; class Daire ; int r; Daire(int _r):r(_r) int ral() const return r; void rata(int _r) r = _r; float alan() const; float Daire::alan() const return PI*r*r; int main() Daire d(3); float alan = d.alan(); cout<<"alan:"<<alan<<endl; return 0; ÇIKTI Alan:28.26 Dairenin alanını hesaplayan sabit fonksiyon 13
Dinamik Bellek Kullanımı Programın çalışması sırasında bellekten yer alınıp kullanılmasına dinamik bellek kullanımı adı verilir Bellekten yer alma işlemi new komutuyla, yeri geri verme işlemi delete komutu ile gerçekleştirir Bellekten alınan isimsiz nesnenin adresini bir göstergeye atayıp üyelerine işaret operatörü (->) ile erişebiliriz. 14
Örnek #include <iostream> using namespace std; class Kare int kenar; void oku(); int cevre(); ; void Kare::oku() cout<<"kenari girin:"; cin>>kenar; int Kare::cevre() return 4*kenar; int main() Kare* p=new Kare; p->oku(); cout<<"cevre="<<p->cevre()<<endl; delete p; return 0; ÇIKTI Kenari girin:5 Cevre=20 p tarafından gösterilen isimsiz nesne yaratılır p kullanarak cevre() fonksiyonu çağrılır p kenar 6 15
Dinamik Bellek Kullanımı... Program bitiminde dinamik nesne yok edilir delete p; Dinamik nesne yok edilmez ise, p tarafından gösterilen yer başka değişkenler için kullanılamaz ve atık haline gelir. İşletim sistemi tarafından atık toplama (garbage collection) yapılana kadar da belleğin bu kısmını kullanılamaz. 16
Dinamik Bellek Kullanımı... Aynı şekilde bir dinamik nesne tanımı sırasında ilk değerleri atamak için yapıcı fonksiyona parametre yollanabilir class Kisi int ogrno; string isim; Kisi(int _ogrno,string _isim):ogrno(_ogrno),isim(_isim) void yaz(); ; void Kisi::yaz() //.. int main() q nun gösterdiği nesne için yapıcı çağrılır Kisi *q =new Kisi(1484, "Can Oz");... delete q; return 0; q ogrno 1484 ogrno Canan Oz 17
this Göstergesi Belleği etkin kullanmak için sınıflarda tanımlanan üye fonksiyonlar o sınıf tipindeki her nesnenin içine tekrar tekrar kopyalanmaz. Üye fonksiyonun tek kopyasını tüm nesneler paylaşır. Fonksiyonun hangi nesne için çağırıldığı ise this göstergesi tarafından belirlenir. Sistemde önceden tanımlanmış this göstergesi her zaman fonksiyonu çağıran nesnenin kendisini gösterir. 18
Örnek class A int x; A(int _x):x(_x) void yaz(); ; void A::yaz() cout<<"x= "<<x<<endl; int main() A n1(1),n2(2); n1.yaz(); n2.yaz(); return 0; this this x 1 n1 x 2 n2 void yaz() cout<< this->x <<endl; 19
Fonksiyon Zincirleme İng. Function chaining Bir fonksiyonun döndürdüğü nesneyi kullanarak başka bir fonksiyon çağırmasıdır 20
Örnek #include <iostream> using namespace std; class Sayi int n; Sayi(int _n=0):n(_n) Sayi& ekle(int); void yaz(); ; Sayi& Sayi::ekle(int x) n+=x; return *this; void Sayi::yaz() cout<<"n= "<<n<<endl; int main() Sayi s(1); s.ekle(2).ekle(3).yaz(); return 0; ÇIKTI n=6 İçinde bulunduğumuz nesneyi döndürür 21
Statik Sınıf Üyeleri İng. Static class member Bir sınıf tipindeki tüm nesnelerin ortak kullanabildikleri üyelerdir static anahtar kelimesi ile tanımlanır 22
Örnek #include <iostream> using namespace std; class Bir static int x; Bir() x++; ; int Bir::x= 0; int main() Bir n1,n2,n3; cout<< Nesnelerin sayisi: <<n1.x<<endl; return 0; ÇIKTI Nesnelerin sayisi: 3 x 1 2 3 x x x n1 n2 n3 n1 n1 n2 n1 n2 n3 23
İng. Header file Özel Başlık Dosyası Sınıf tanımlarını ve üye fonksiyonlarının protototiplerini içeren dosyadır 24
Örnek class A int i; void yaz() y = 5.2; cout<<i<< <<y; private: float y; int z; ; #include <iostream> #include "A.h int main() A nsn; nsn.i = 5; nsn.yaz(); return 0; programın a.h dosyasının içeriğini görmesini sağlar class A int i; void yaz() y=5.2;... a.h #include <iostream.h> #include a.h main() A nsn; nsn.i = 5; x.yaz();. prg.cpp 25
#ifndef, #ifdef ve #endif Önişlemci Komutları Kaynak dosyaları, birden çok başlık dosyası içerebilir ve bu başlık dosyalarından bazıları diğer başlık dosyalarını da içerebilir. Bu tür durumlarda, bir isim birden fazla başlık dosyasında tekrar tekrar tanımlanabilir. Derleyici ismi hangi başlık dosyasından çağıracağını bilemeyeceği için hata üretir. Bu tür problemleri engellemek amacı ile aşağıdaki önişlemci komutlarından yararlanılır. #ifndef (eğer tanımlı değilse, if not defined): söz konusu değişkenin başka bir başlık dosyasında tanımlanmama koşulunu ifade eder #ifdef (eğer tanımlı ise (if defined): söz konusu değişkenin başka başlık dosyasında tanımlanmış olma koşulunu ifade eder. #endif: #ifdef ve #ifndef koşul ifadelerini sonlandırır. 26
Örnek A.h dosyası dahil edilir // ----------- A.h ----------- #ifndef A_H #define A_H class A float y; int z; int i; ; #endif // ----------- B.h ----------- #include "A.h" class B double x; ; // ------------ Uygulama.cpp ----------- #include "A.h #include "B.h" #include <iostream> using namespace std; int main() A a; B b; a.i = 10; b.x = 20; cout<<a.i; cout<<b.x; return 0; A.h dosyası dahil edilir B.h dosyası dahil edilir 27