Memory-Based Learning Instance-Based Learning K

advertisement
NESNEYE YÖNELİK PROGRAMLAMA
NESNELERİN YARATILMASI VE YOK EDİLMESİ,
FONKSİYONLARIN AŞIRI YÜKLENMESİ,
CONST NESNELER,
ELEMAN NESNELER,
DİNAMİK BELLEK YÖNETİMİ
Özlem AYDIN
Trakya Üniversitesi
Bilgisayar Mühendisliği Bölümü
NESNELERİN YARATILMASI VE YOK EDİLMESİ - 1
Örnek:
// DEMO.CPP
#include <iostream>
#include <cstring>
using namespace std;
class Demo
{
public:
Demo(const char *nm);
~Demo();
private:
char isim[20];
};
NESNELERİN YARATILMASI VE YOK EDİLMESİ - 2
Demo::Demo( const char *nm )
{
strncpy( isim, nm, 20 );
cout << isim << “ icin yapici fonksiyon cagrimi\n”;
}
Demo::~Demo()
{
cout << isim << “ icin yikici fonksiyon cagrimi\n”;
}
void fonk()
{
Demo yerelFonkNesnesi(“yerelFonkNesnesi”);
static Demo staticNesne(“statikNesne”);
cout << ”fonk icinde” << endl;
}
NESNELERİN YARATILMASI VE YOK EDİLMESİ - 3
Demo globalNesne(“globalNesne”);
int main()
{
Demo yerelMainNesnesi(“yerelMainNesnesi”);
cout << “fonk cagrimindan once, main icinde\n”;
fonk();
cout << “fonk cagrimindan sonra, main icinde\n”;
}
return 0;
NESNELERİN YARATILMASI VE YOK EDİLMESİ - 4

Yerel nesneler için, yapıcı fonksiyon nesnenin
bildirimi yapıldığında, yıkıcı fonksiyon ise nesne
bildiriminin yapıldığı bloktan çıkarken çağrılır.

Global nesneler için, yapıcı fonksiyon program
başlarken, yıkıcı fonksiyon ise program sona
ererken çağrılır.

Statik nesneler için, yapıcı fonksiyon nesnenin
bildiriminin yapıldığı fonksiyona ilk girişte, yıkıcı
fonksiyon ise program sona ererken çağrılır.
NESNELERİN YARATILMASI VE YOK EDİLMESİ - 5
Program çıktısı:
globalNesne icin
yerelMainNesnesi
fonk cagrimindan
yerelFonkNesnesi
statikNesne icin
fonk icinde
yerelFonkNesnesi
fonk cagrimindan
yerelMainNesnesi
statikNesne icin
globalNesne icin
yapici fonksiyon cagrimi
icin yapici fonksiyon cagrimi
once, main icinde
icin yapici fonksiyon cagrimi
yapici fonksiyon cagrimi
icin yikici fonksiyon cagrimi
sonra, main icinde
icin yikici fonksiyon cagrimi
yikici fonksiyon cagrimi
yikici fonksiyon cagrimi
ELEMAN SAHALARA ERİŞİM - 1

Şu anki haliyle, Tarih sınıfı gun, ay ve yil bileşenlerine erişim izni vermemektedir;
örneğin, bir Tarih nesnesinin ay değerini okuyup değiştiremezsiniz. Bu sorunu
gidermek için Tarih sınıfı aşağıdaki gibi değiştirilebilir:
class Tarih
{
public:
Tarih( int mn, int dy, int yr );
int aySoyle();
int gunSoyle();
int yilSoyle();
int ayBelirle( int mn );
int gunBelirle ( int dy );
int yilBelirle( int yr );
void goruntule();
~Tarih();
private:
int ay, gun, yil;
};
ELEMAN SAHALARA ERİŞİM - 2

Erişim fonksiyonları şöyle tanımlanabilir:
inline int Tarih::aySoyle()
{ return ay; }
inline int Tarih::gunSoyle()
{ return gun; }
inline int Tarih::yilSoyle()
{ return yil; }
ELEMAN SAHALARA ERİŞİM - 3
void Tarih::ayBelirle( int mn )
{
ay = max( 1, mn );
ay = min( ay, 12 );
}
void Tarih::gunBelirle( int dy )
{
static int uzunluk[]={0,31,28,31,30,31,3031,31,30,31,30,31};
gun = max( 1, dy );
gun = min( gun, uzunluk[ay] );
}
void Tarih::yilBelirle( int yr )
{
yil = max( 1, yr );
}
ELEMAN SAHALARA ERİŞİM - 4
 Aşağıdaki örnekte main fonksiyonu yeni tanımladığımız
erişim fonksiyonlarını kullanmaktadır:
int main()
{
int i;
Tarih sonTarih( 3, 10, 2005 );
i = sonTarih.aySoyle();
sonTarih.ayBelirle( 4 );
sonTarih.ayBelirle(sonTarih.aySoyle()+1);
return 0;
}
ELEMAN inline FONKSİYONLAR

Soyle fonksiyonları çok kısa olmaları nedeniyle ve çağrımlarının
“overhead” içermemesi nedeniyle inline olarak bildirildiler.

Eleman fonksiyonların gövdesini sınıf bildirimi içine yerleştirmeniz halinde
inline anahtar sözcüğünü kullanmadan inline bildirimlerini sağlamış
olursunuz:
class Tarih
{
public:
Tarih( int mn, int dy, int yr );
int aySoyle() { return ay; }
int gunSoyle() { return gun; }
int yilSoyle() { return yil; }
// ...
};
YAPICI FONKSİYONLARIN AŞIRI YÜKLENMESİ - 1

Yeni eleman fonksiyonlarımızla, bir Tarih nesnesinin nasıl yaratılacağını
yeniden belirleyebiliriz:
class Tarih
{ public:
Tarih();
Tarih( int mn, int dy, int yr );
// ...
};
Tarih::Tarih() { ay = gun = yil = 1;}
Tarih::Tarih( int mn, int dy, int yr )
{
ayBelirle( mn );
gunBelirle( dy );
yilBelirle( yr ); }
YAPICI FONKSİYONLARIN AŞIRI YÜKLENMESİ - 2
void main()
{
Tarih dogum1;
Tarih dogum2( 12, 25, 1990 );
dogum1.ayBelirle( 3 );
dogum1.gunBelirle( 12 );
dogum1.yilBelirle( 1985 );
}
const NESNELER VE ELEMAN FONKSİYONLAR-1

Değişkenleri olduğu gibi nesneleri de
bildirebilirsiniz:
const Tarih dogum1( 7, 4, 1776 );
const
olarak

Bu tür bildirimler nesnenin sabit olduğu ve dolayısıyla hiçbir
eleman sahasının değiştirilemeyeceği anlamına gelir.

Bir değişkeni const olarak bildirdiğinizde, derleyici bu
değişkenin değerini değiştirebilecek işlemleri tespit edip
uygun hata mesajlarını üretebilir. Ancak, derleyici bir eleman
fonksiyonun
nesnenin
eleman
sahalarını
değiştirip
değiştiremeyeceğini belirleyemez. Bu nedenle, hiçbir
(sıradan) eleman fonksiyon sabit bir nesne için çağrılamaz.
const NESNELER VE ELEMAN FONKSİYONLAR-2

Eğer bir eleman fonksiyon nesnenin hiçbir eleman
sahasını değiştirmiyorsa const olarak bildirilebilir ve bu
şekilde sabit nesneler için çağrılabilir.

const anahtar sözcüğü sabit fonksiyonların hem
bildiriminde hem de tanımlanmasında, parametre
listesinden sonra yer alır.

Sabit eleman fonksiyonlar ne nesnelerinin eleman
sahalarını değiştirebilir, ne de sabit olmayan eleman
fonksiyonları çağırabilirler.

Eleman fonksiyonlarınızı mümkün olduğunca sabit olarak
bildirmelisiniz. Bu, sınıfınızı kullananların sabit nesneler
bildirmelerine izin verecektir.
const NESNELER VE ELEMAN FONKSİYONLAR-3
class Tarih
{
public:
Tarih(int mn, int dy, int yr);
int aySoyle() const;
int gunSoyle() const;
int yilSoyle() const;
int ayBelirle(int mn);
int gunBelirle(int dy);
int yilBelirle(int yr);
void goruntule() const;
~Tarih();
private:
int ay, gun, yil;
};
inline int Tarih::aySoyle() const { return ay; }
// ...
int i; const Tarih dogum1( 7, 4, 1776 );
i = dogum1.yilSoyle(); // Legal
dogum1.yilBelirle( 1492 );// Error
ELEMAN NESNELER - 1

Bir sınıf, nesneleri eleman olarak içerebilir. Bu şekilde diğer sınıfları
bileşen olarak kullanma suretiyle yeni bir sınıf tanımlama işlemine
“bileşim (composition)” denir:
class KisiBilgisi
{
public:
// Public eleman fonksiyonlar...
private:
char isim[30];
char adres[60];
Tarih dogumTarihi;
};
dogumTarih nesnesi KisiBilgisi sınıfından bir nesne yaratılıncaya
kadar yaratılmaz.
ELEMAN NESNELER - 2
Bir eleman nesne için yapıcı fonksiyon çağrımı, eleman
nesneye ilk değer atamalarının yapılmasını gerektirir.
Bunun icin yapılması gereken aşağıda örneklenmiştir:

class KisiBilgisi
{
public:
KisiBilgisi(char *nm, char *adr, int mn, int dy, int yr);
// ...
private:
// ...
};
ELEMAN NESNELER - 3
KisiBilgisi::KisiBilgisi(char *nm, char *adr,int mn, int dy, int yr)
:dogumTarihi( mn, dy, yr )
{
strncpy( isim, nm, 30 );
strncpy( adres, adr, 60 );
}
 İlk önce Tarih sınıfının yapıcı fonksiyonu çağrılır; böylelikle
dogumTarihi nesnesi ilk değerlerini KisiBilgisi sınıfının yapıcı
fonksiyonu çalıştırılmadan alır.
Örnek
#include <iostream>
using namespace std;
#define SIZE 100
// Stack sınıfı:
class Stack {
int stck[SIZE];
int tos;
public:
Stack(); // yapıcı (constructor)
~Stack(); // yıkıcı (destructor)
void push(int i);
int pop();
};
Örnek – devam…
// Yapici Fonksiyon
Stack::Stack()
{
tos = 0;
cout << "Stack Initialized\n";
}
// Yikici Fonksiyon
Stack::~Stack()
{
cout << "Stack Destroyed\n";
}
Örnek – devam…
void Stack::push(int i)
{
if(tos==SIZE) {
cout << "Stack is full.\n";
return;
}
stck[tos] = i;
tos++;
}
Örnek – devam…
int Stack::pop()
{
if(tos==0) {
cout << "Stack underflow.\n";
return 0;
}
tos--;
return stck[tos];
}
Örnek – devam…
int main()
{
Stack a, b; // iki stack nesnesi yaratildi
a.push(1);
b.push(2);
a.push(3);
b.push(4);
cout << a.pop()
cout << a.pop()
cout << b.pop()
cout << b.pop()
return 0;
}
<<
<<
<<
<<
" ";
" ";
" ";
"\n";
Örnek – devam…
Program Çıktısı:
Stack Initialized
Stack Initialized
3 1 4 2
Stack Destroyed
Stack Destroyed
Dinamik Bellek Yönetimi – C dili

C’de çalışma zamanında alınıp kullanılabilen bellek
bölgesine “heap” denir.

C’de heap’ten bellek istemek için malloc fonksiyonu
kullanılır:
struct t *t_ptr;
t_ptr = (struct t *) malloc(sizeof(struct t));

malloc fonksiyonu ayrılmış belleğin başlangıcına bir
işaretçi geri verir.
Dinamik Bellek Yönetimi – C++ dili

C++ “free store” olarak adlandırılan bir bellek
bölgesinden dinamik olarak nesne yaratmak ya da yok
etmek için bellek kullanımına izin verir.
p-var=new type;
delete p-var;

type, bellekte yer ayrılacak nesnenin tipidir.

p-var, o tipe olan işaretçidir.

new operatörü, type ile tipi belirtilen nesneyi taşıyacak
kadar genişliği olan, dinamik olarak ayrılmış belleğe bir
işaretçi döndürür.
Dinamik Bellek Yönetimi -- Örnek
Tarih *Ptr1, *Ptr2;
int i;
Ptr1 = new Tarih; //Varsayilan yapıcı fonk. cagrilir
i = Ptr1->aySoyle(); //1 (varsayilan deger) doner
Ptr2 = new Tarih(3,15,1985); //Yapıcı Fonk. cagrilir
i = Ptr2->aySoyle();
//3 doner
Dinamik Bellek Yönetimi – new

Derleyici new operatörünün döndürdüğü işaretçinin
kendisi için bellek ayrılan nesne için olup olmadığını
kontrol eder:
void *Ptr;
Ptr = new Tarih; // Tip uyumsuzluğu, hata!

Nesne için ayrılan yerin döndürdüğü işaretçi nesne ile
aynı tipte olmak zorundadır.
Tarih *Ptr;
Ptr = new Tarih;
Dinamik Bellek Yönetimi - delete

Nasıl malloc fonksiyonunun eşleniği olan bir free
fonksiyonu varsa, new operatörünün de eşleniği olan bir
delete operatörü vardır.

delete operatörü ayrılan bellek bölgelerini daha sonra
kullanılabilmek üzere “free store” bölgesine iade eder:
Tarih *Ptr1;
int i;
Ptr1 = new Tarih(3, 15, 1985);
i = Ptr1->aySoyle();
delete Ptr1;
Dinamik Bellek Yönetimi - delete

delete operatörü belleği geri vermeden önce
otomatik olarak yıkıcı fonksiyonu çağırır.

delete operatörünü yalnızca new ile döndürülen
işaretçilere ve yalnızca bir kez uygulamalısınız.

delete operatörünü, 0 değerli bir işaretçiye (“null
pointer”) uygulayabilirsiniz.
“Free store” ve diğer veri tipleri - 1

new ve delete operatörlerini yalnızca sınıflarla değil
diğer derleyici ile birlikte gelen veri tipleri ile de
kullanabilirsiniz:
int *ip;
ip = new int;
//* ip = new int(3);
// ...
delete ip;
* Dinamik olarak yer ayrılan bir nesneye ilk değer
verebilirsiniz.
“Free store” ve diğer veri tipleri - 2

new kullanarak bir boyutlu bir diziye dinamik olarak yer
ayırabilirsiniz.

Dinamik olarak ayrılmış diziyi silmek için delete [ ]
kullanılır. Bu gösterim ile derleyicinin dizideki her
elemanın yıkıcı fonksiyonunu çağırmasına neden olur.
int uzunluk;
char *cp;
// uzunluk degiskenine bir deger atanir
cp = new char[uzunluk];
// ...
delete [] cp;
Kaynaklar

Prof. Dr. Yılmaz Kılıçaslan, Nesneye Yönelik Programlama dersi
sunumları
Download