siniflar gİrİŞ

68
SINIFLAR GİRİŞ Yılmaz Kılıçaslan

Upload: ray

Post on 22-Jan-2016

129 views

Category:

Documents


0 download

DESCRIPTION

SINIFLAR GİRİŞ. Yılmaz Kılıçaslan. Sunum Planı. Bu derste sınıf mekanizmasını şu yönleriyle inceleyeceğiz: Sınıf kavramının evrimine kısa bir bakış Bir ara form olarak C yapıları (structures). Sınıf bildirimi Sınıfa ait nesnelerin kullanımı Eleman sahalar ve eleman fonksiyonlar - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: SINIFLAR GİRİŞ

SINIFLARGİRİŞ

Yılmaz Kılıçaslan

Page 2: SINIFLAR GİRİŞ

Sunum Planı

Bu derste sınıf mekanizmasını şu yönleriyle inceleyeceğiz:

– Sınıf kavramının evrimine kısa bir bakış– Bir ara form olarak C yapıları (structures).– Sınıf bildirimi– Sınıfa ait nesnelerin kullanımı– Eleman sahalar ve eleman fonksiyonlar– Yapıcı ve yıkıcı fonksiyonlar– const nesneler ve eleman fonksiyonlar– Eleman nesneler 2

Page 3: SINIFLAR GİRİŞ

Programlama Dillerinin Evrimi

Most new industrial-strength software systems are larger and more complex than their predecessors were even just a few years ago. This growth in complexity has prompted a significant amount of useful applied research in software engineering, particularly with regard to decomposition, abstraction, and hierarchy. The development of more expressive programming languages has complemented these advances. The trend has been a move away from languages that tell the computer what to do (imperative languages) toward languages that describe the key abstractions in the problem domain (declarative languages). (Booch, G. 1998)

3

Page 4: SINIFLAR GİRİŞ

Sınıflara Giden Soyutlama Süreci - 1

Wegner (1976), yüksek-düzeyli programlama dillerini, ilk kez kullandıkları dil özelliklerine dayanarak, bir kuşak sınıflamasına tabi tutmuştur:

Birinci-Kuşak Diller (1954-1958)

 – FORTRAN I Matematiksel ifadeler

– ALGOL 58 Matematiksel ifadeler

– Flowmatic Matematiksel ifadeler

– IPL V Matematiksel ifadeler

4

Page 5: SINIFLAR GİRİŞ

Sınıflara Giden Soyutlama Süreci - 2

İkinci-Kuşak Diller (1959~1961)

– FORTRAN II Alt rutinler, bağımsız derleme

– ALGOL 60 Blok yapıları, veri tipleri

– COBOL Veri tanımlama, dosya işlemleri

– Lisp Liste işleme, işaretçiler, ‘garbage collection’

5

Page 6: SINIFLAR GİRİŞ

Sınıflara Giden Soyutlama Süreci - 3

Üçüncü-Kuşak Diller (1962-1970)

– PL/1 FORTRAN + ALGOL + COBOL

– ALGOL 68 ALGOL 60’ın sıkı takipçisi

– Pascal ALGOL 60’ın gevşek takipçisi

– Simula Sınıflar, veri soyutlama

6

Page 7: SINIFLAR GİRİŞ

Sınıflara Giden Soyutlama Süreci - 4

Kuşak Boşluğu (1970-1980)

Birçok farklı programlama dili türedi ama çok azı varlığını sürdürebildi. Bu dönemde ortaya çıkan dillerin sayısı binlerle ifade edilebilecek miktardadır. Bugün neredeyse hiçbirimizin hatırlamadığı veya bilmediği birçok dil icat edilmiştir. Fred, Tranquil, Chaos bunlardan birkaçıdır. Bu sonuncusunun adı, dönemin kaotik niteliğiyle çok iyi örtüşmektedir.

7

Page 8: SINIFLAR GİRİŞ

Programlama Dillerinin Topolojisi - 1

8

The Topology of First- and Early Second-Generation Programming Languages

Page 9: SINIFLAR GİRİŞ

Programlama Dillerinin Topolojisi - 2

9

The Topology of Late Second- and Early Third-Generation Programming Languages

Page 10: SINIFLAR GİRİŞ

Programlama Dillerinin Topolojisi - 3

10

The Topology of Late Third-Generation Programming Languages

Page 11: SINIFLAR GİRİŞ

Programlama Dillerinin Topolojisi - 4

11

The Topology of Small- to Moderate-Sized Applications Using Object-Based and Object-Oriented Programming Languages

Page 12: SINIFLAR GİRİŞ

YAPILAR - 1

Eğer tarihler üzerine çok sık işlem yapan bir C programı yazıyorsanız, tarihleri gösteren yeni bir veri tipini yapı (structure) olarak tanımlayabilirsiniz:

struct tarih{ int ay;

int gun; int yil;};//...struct tarih dogum;dogum.ay = 1;dogum.gun = 23;dogum.yil = 1985;

Page 13: SINIFLAR GİRİŞ

YAPILAR - 2 printf’e parametre olarak geçirmek suretiyle bir tarih yapısını

yazdıramazsınız. Ya yapınının her elemanını ayrı ayrı yazdırmalısınız ya da yapıyı bir bütün olarak yazdırmak için kendi fonksiyonunuzu yazmalısınız:

void tarih_goruntule(struct tarih *tr){static char *isim[] = {“zero”,”ocak”,”subat”,”mart”,”nisan”,

“mayis”,”haziran”,”temmuz”,”agustos”, “eylul”,”ekim”,”kasim”,”aralik”};

printf(“%s %d %d”,isim[tr->gun], tr->gun,tr->yil);} 13

Page 14: SINIFLAR GİRİŞ

YAPILAR - 3

Tarihler üzerinde, iki tanesini karşılaştırmak gibi, benzer işlemler yapmak için de, ya yapı elemanlarını ayrı ayrı işlemelisiniz ya da tarih yapılarını parametre olarak kabul edip söz konusu işlemleri sizin için yapan fonksiyonlar tanımlamalısınız.

14

Page 15: SINIFLAR GİRİŞ

YAPILAR - 4

Tarihleri yapı olarak göstermenin çeşitli dezavantajları vardır:

– Bir tarih yapısının geçerli bir tarihi içerdiği garanti edilemez.

– Bir kez tarih veri tipini programlarınızda kullandığınızda, kodlaması üzerinde değişiklik yapmak çok zorlaşır.

15

Page 16: SINIFLAR GİRİŞ

YAPILAR - 5

Bu problemlerden kaçınmak için daha fazla programlama eforu göstermelisiniz. Örneğin,

– belirtilen değerlerin geçerliliğini test eden bir fonksiyon kullanabilirsiniz ve

– yapının eleman sahalarına doğrudan erişmek yerine, erişim fonksiyonları tanımlayabilirsiniz.

16

Page 17: SINIFLAR GİRİŞ

SINIF BİLDİRİMİ - 1

C++, tanımladığınız yeni veri tiplerinin güvenliğini, bir veri tipi ve bu veri tipi üzerindeki işlemleri aynı anda tanımlamanıza imkan veren sınıflar aracılığıyla sağlar.

17

Page 18: SINIFLAR GİRİŞ

SINIF BİLDİRİMİ - 2

Bir sınıf bildirimi, yalnızca verileri değil eleman fonksiyonları da içermesi haricinde, yapı bildirimine benzer:

class sınıf_ismi{özel korumalı veri ve fonksiyonlar

erişim_etiketi: veri ve fonksiyonlar erişim_etiketi:

veri ve fonksiyonlar // ...erişim_etiketi: veri ve fonksiyonlar } nesne_listesi;

18

Page 19: SINIFLAR GİRİŞ

SINIF BİLDİRİMİ - 3

Örnek:

// Tarih sinifi#include <iostream>using namespace std;

class Tarih{ public:

Tarih( int mn, int dy, int yr ); void goruntule(); ~Tarih();

private: int ay, gun, yil;

};19

Page 20: SINIFLAR GİRİŞ

FONKSİYONLARIN TANIMLANMASI - 1

// Bazı gerekli fonksiyonlarinline int max( int a, int b )

{if ( a > b ) return a;return b;

}

inline int min( int a, int b ) {

if ( a < b ) return a;return b;

}20

Page 21: SINIFLAR GİRİŞ

FONKSİYONLARIN TANIMLANMASI - 2

// Yapici Fonksiyon Tarih::Tarih( int mn, int dy, int yr )

{ static int uzunluk[] = {0,31,28,31,30, 31,30,31,31,30,31,30,31}; //366 gun iceren yillari ihmal ediyoruz.

ay = max( 1, mn ); ay = min( ay, 12 );

gun = max( 1, dy ); gun = min( gun, uzunluk[ay] );

yil = max(1, yr ); }

21

Page 22: SINIFLAR GİRİŞ

FONKSİYONLARIN TANIMLANMASI - 3

// Tarih Bilgisi Goruntuleme Fonksiyonu void Tarih::goruntule()

{static char *isim[] =

{ “zero”,”ocak”,”subat”,”mart”,”nisan”,

“mayis”,”haziran”,”temmuz”,”agustos”,“eylul”,”ekim”,”kasim”,”aralik” };

cout << isim[ay] << ‘ ‘<< gun << “, “ << yil;

}22

Page 23: SINIFLAR GİRİŞ

FONKSİYONLARIN TANIMLANMASI - 4

// Yikici Fonksiyon Tarih::~Tarih()

{ // Hicbir sey yapma}

23

Page 24: SINIFLAR GİRİŞ

SINIFLARIN KULLANIMI-1

// Tarih sinifinin kullanimina bir örnekint main()

{// Gecerli bir Tarih bildirimiTarih dogum1(3, 12, 1985); // Gecersiz bir Tarih bildirimiTarih dogum2(23, 259, 1966);

dogum1.goruntule();cout << ‘\n’;dogum2.goruntule();cout << ‘\n’;

return 0;}

24

Page 25: SINIFLAR GİRİŞ

SINIFLARIN KULLANIMI-2

C’de tarihleri görüntülemek için her bir yapının adresini ilgili fonksiyona göndermeniz gerekecekti:

// C’de tarihlerin goruntulenmesigoruntule(&dogum1);goruntule(&dogum2);

25

Page 26: SINIFLAR GİRİŞ

SINIFLARIN KULLANIMI-3

C++ her bir eleman fonksiyonu bir yapının eleman sahasına erişmekte kullanılan sözdizimine benzer bir sözdizim ile çağırır:

dogum1.goruntule();dogum2.goruntule();

C++’daki sözdizim bir veri tipi ile bu veri tipi üzerinde işlem yapacak fonksiyonlar arasındaki sıkı ilişkiyi vurgulamaktadır. Bu durum, sizin goruntule fonksiyonunu Tarih sınıfının bir parçasıymış gibi düşünmenize yol açar. Fakat, gerçekte bu birleşme yalnızca sözdizimseldir: Her Tarih nesnesi goruntule fonksiyonunun bir kopyasına sahip değildir; her nesne yalnızca kendi eleman sahalarını içerir.

26

Page 27: SINIFLAR GİRİŞ

SINIFIN ELEMANLARI

Görüldüğü gibi, sınıf bildirimi (int tipinde ay, gun, yil sahaları gibi) eleman sahalara sahip olması yönüyle yapı bildirimine benzemektedir. Fakat, bazı yönlerden de C’deki yapı bildiriminden ayrılmaktadır. Örneğin:

– public ve private anahtar sözcüklerini,

– (goruntule gibi) fonksiyon bildirimlerini ve

– (Tarih ve ~Tarih gibi) yapıcı ve yıkıcı olarak adlandırılan özel fonksiyonları

içermektedir. Şimdi bu farklara ayrı ayrı bakalım.

27

Page 28: SINIFLAR GİRİŞ

ERİŞİM DÜZEYLERİ (public ve private)-1

public ve private etiketleri kendilerini takip eden elemanların erişilebilirlik düzeyini belirler. Belirlenen erişim düzeyi bir sonraki etikete ya da sınıf tanımının sonuna kadar devam eder.

private elemanlara yalnızca eleman fonksiyonlar erişebilir. (Daha sonra, bu ayrıcalığa arkadaş sınıf veya fonksiyonların da sahip olduğunu göreceğiz.)

public elemanlara eleman fonksiyonlar dışında, sınıfa ait nesnenin kapsam alanında olması koşuluyla, programın herhangi bir fonksiyonundan erişilebilir.

28

Page 29: SINIFLAR GİRİŞ

ERİŞİM DÜZEYLERİ (public ve private)-2

Sınıfa ait olmayan bir fonksiyon bir private elemana erişme girişiminde bulunursa derleyici hata üretir:

int main(){

int i; Tarih dogum1( 3, 12, 1985 )

i = dogum1.ay;//Error: private saha okunamaz dogum1.gun=1;//Error: private saha degistirilemez

return 0;}

Fakat, public elemanlara (örn. goruntule fonksiyonu) erişim mümkündür.

29

Page 30: SINIFLAR GİRİŞ

ERİŞİM DÜZEYLERİ (public ve private)- 3

Birçok programcının private elemanları bir grupta ve public elemanları bir başka grupta toplamayı tercih etmesine karşın, private ve public etiketleri bir sınıfın tanımında istenilen sayıda yinelenebilir.

Bütün sınıf tanımlamalarında varsayılan başlangıç modu private erişim modudur. Fakat, yine de okunurluğu artırmak için bütün bölümleri etiketlemekte yarar vardır.

Tarih sınıfında da örneklendiği gibi, C++’da yaygın olan bir konvansiyon public arayüzün bütünüyle fonksiyonlardan oluşturulmasıdır; bir private veriyi bu amaç için tasarlanmış public bir eleman fonksiyon ile görüntüleyebilir ya da değiştirebilirsiniz.

30

Page 31: SINIFLAR GİRİŞ

ELEMAN FONKSİYONLAR- 1

Eleman fonksiyonların prototipi ait olduğu sınıfın bildirimi içinde yer alır.

Sınıf dışında sınıfa ait bir fonksiyon tanımlanırken, fonksiyonun ismi, sınıfın ismi ve kapsam çözümleme operatörü birlikte kullanılır:

Tarih::goruntule()

Bu gösterim fonksiyonun bir sınıfa ait olduğunu ve isminin bu sınıfın kapsam alanında yer aldığını ifade etmektedir. Bu kapsam alanın dışında aynı isim, başka fonksiyonları adlandırmak için kullanılabilir.

31

Page 32: SINIFLAR GİRİŞ

ELEMAN FONKSİYONLAR- 2

Her bir versiyonun parametre listesi ile diğerlerinden ayrılması koşuluyla, bir eleman fonksiyonu, herhangi bir diğer fonksiyon gibi aşırı yükleyebilirsiniz.

Eleman fonksiyonlar, sınıflarının diğer elemanlarına nesne ismi belirtmeksizin erişebilirler.

32

Page 33: SINIFLAR GİRİŞ

ELEMAN FONKSİYONLAR- 3

Bir eleman fonksiyon, nesneye işaret eden bir işaretçi aracılığıyla da çağrılabilir:

Tarih doğum1( 3, 12, 1985 )

Tarih *tarihPtr = &doğum1;

tarihPtr -> goruntule();

33

Page 34: SINIFLAR GİRİŞ

ELEMAN FONKSİYONLAR- 4

Bir eleman fonksiyon bir nesne referansı aracılığıyla bile çağrılabilir:

Tarih doğum1( 3, 12, 1985 )

Tarih &digerTarih = doğum1;

digerTarih.goruntule();

34

Page 35: SINIFLAR GİRİŞ

YAPICI FONKSİYONLAR - 1

C’de kodladığımız tarih “structure”ının geçerli değerleri içermeyi doğrudan garanti edememek gibi bir dezavantajı olduğunu görmüştük. C++’da bu tür bir dezavantajı gidermenin bir yolu yapıcı fonksiyon yazmaktır.

Yapıcı fonksiyonlar sınıfınızın herhangi bir nesnesinin bildirimi yapıldığında, otomatik olarak çağrılan özel türde ilk değer atama fonksiyonlarıdır; ilk değer almamış nesnelerin kullanımından kaynaklanabilecek hataları engellerler.

35

Page 36: SINIFLAR GİRİŞ

YAPICI FONKSİYONLAR - 2

Yapıcı fonksiyonun ait olduğu sınıf ile aynı isme sahip olması gerekir. Örneğin, Tarih sınıfının yapıcı fonksiyonu Tarih olarak adlandırılmıştır.

Tarih yapıcı fonksiyonunun gerçeklemesine baktığımızda (bkz. Slayt 21), fonksiyonun yalnızca nesnenin eleman sahalarına ilk değer atamakla kalmayıp belirtilen değerlerin geçerliliğini de kontrol ettiğini görüyoruz. Bu yapıcı fonksiyonlar aracılığıyla nesnelerin anlamlı değerler içermesini sağlamanın bir diğer yoludur.

36

Page 37: SINIFLAR GİRİŞ

YAPICI FONKSİYONLAR - 3

Bir sınıf nesnesinin kapsam alanına her girişinde yapıcı fonksiyon koşturulur.

Nesne bildirimi tamsayı bildirimine benzer. Önce veri tipi, ardından da nesnenin ismi belirtilir:

Tarih doğum1( 3, 12, 1985 );

Fakat, nesnenin bildirimi parantez içinde bir argüman listesi de içerebilir. Bu argümanlar yapıcı fonksiyona parametre değeri olarak gönderilir ve nesnenin ilk değer atamasında kullanılır. 37

Page 38: SINIFLAR GİRİŞ

YAPICI FONKSİYONLAR - 4

Bir yapıcı fonksiyon bildiriminde bulunurken, void dahil, döndürülecek herhangi bir değer tipi belirtemezsiniz. Dolayısıyla, bir yapıcı fonksiyon herhangi bir return ifadesi de içermez.

Yapıcı fonksiyonlarınızı aşırı yükleyerek, bir sınıf için birden fazla yapıcı fonksiyon bildiriminde bulunabilirsiniz.

Gerçekte, bir sınıf tanımlarken herhangi bir yapıcı fonksiyon tanımlama zorunluluğu yoktur. Eğer hiçbir yapıcı fonksiyon tanımlamazsanız derleyici otomatik olarak hiçbir parametre almayan ve hiçbir şey yapmayan bir tane üretir. 38

Page 39: SINIFLAR GİRİŞ

YIKICI FONKSİYONLAR - 1

Yıkıcı fonksiyonlar, tahmin edebileceğiniz gibi, yapıcı fonksiyonların zıt işlevselliğine sahiptirler: Bir sınıf nesnesi kapsam alanının dışına çıkınca otomatik olarak yıkıcı fonksiyon çağrılır.

Yıkıcı fonksiyonun görevi bir nesne yok edilmeden önce gerekli bütün `temizlik’ işlerini yapmaktır.

Yıkıcı fonksiyonların başlarına almak zorunda olduklari ~ sembolü haricinde isimleri sınıflarıyla aynıdır.

39

Page 40: SINIFLAR GİRİŞ

YIKICI FONKSİYONLAR - 2

Yıkıcı fonksiyonları da açıkça tanımlama zorunluluğu yoktur.

Yıkıcı fonksiyonlar aşırı yüklenemez; yalnızca bir tane olmak zorundadırlar.

Yıkıcı bir fonksiyon parametre alamaz ve değer döndüremez.

40

Page 41: SINIFLAR GİRİŞ

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];

}; 41

Page 42: SINIFLAR GİRİŞ

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;}

42

Page 43: SINIFLAR GİRİŞ

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;

}

43

Page 44: SINIFLAR GİRİŞ

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 program 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.

44

Page 45: SINIFLAR GİRİŞ

NESNELERİN YARATILMASI VE YOK EDİLMESİ - 4

Program çıktıları:

globalNesne icin yapici fonksiyon cagrimiyerelMainNesnesi icin yapici fonksiyon cagrimifonk cagrimindan once, main icindeyerelFonkNesnesi icin yapici fonksiyon cagrimistatikNesne icin yapici fonksiyon cagrimifonk icindeyerelFonkNesnesi icin yikici fonksiyon cagrimifonk cagrimindan sonra, main icindeyerelMainNesnesi icin yikici fonksiyon cagrimistatikNesne icin yikici fonksiyon cagrimiglobalNesne icin yikici fonksiyon cagrimi

45

Page 46: SINIFLAR GİRİŞ

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;

};

46

Page 47: SINIFLAR GİRİŞ

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; }

void Tarih::ayBelirle( int mn ){ ay = max( 1, mn ); ay = min( ay, 12 ); }

47

Page 48: SINIFLAR GİRİŞ

ELEMAN SAHALARA ERİŞİM - 3

void Tarih::gunBelirle( int dy ){ static int uzunluk[] = { 0,31,28,31,30,31,30,

31,31,30,31,30,31 }; gun = max( 1, dy );

gun = min( gun, uzunluk[ay] ); }

void Tarih::yilBelirle( int yr ){ yil = max( 1, yr );

48

Page 49: SINIFLAR GİRİŞ

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;} 49

Page 50: SINIFLAR GİRİŞ

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; } // ...};

50

Page 51: SINIFLAR GİRİŞ

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 ); }

51

Page 52: SINIFLAR GİRİŞ

YAPICI FONKSİYONLARIN AŞIRI YÜKLENMESİ - 1

void main(){ Tarih dogum1; Tarih dogum2( 12, 25, 1990 );

dogum1.ayBelirle( 3 ); dogum1.gunBelirle( 12 ); dogum1.yilBelirle( 1985 ); }

52

Page 53: SINIFLAR GİRİŞ

REFERANS DÖNDÜRME - 1

Bazen, C++ programları public eleman sahalar gibi davranan eleman fonksiyon bildirimleri içerirler. Bu fonksiyonlar, private eleman sahalara referans döndürürler:

// KOTU TEKNIKclass Tarih{ public: Tarih( int mn, int dy, int yr ); int &ay();

~Tarih(); private: int ay_elemani, gun_elemani, yil_elemani; };

int &Tarih::ay(){ ay_elemani = max( 1, ay_elemani ); ay_elemani = min( ay_elemani, 12 );

return ay_elemani; }// ...

53

Page 54: SINIFLAR GİRİŞ

REFERANS DÖNDÜRME - 2

void main(){ int i; Tarih sonTarih( 3, 10, 2005 ); i = sonTarih.ay(); sonTarih.ay() = 4;

sonTarih.ay()++; }

54

Page 55: SINIFLAR GİRİŞ

const NESNELER VE ELEMAN FONKSİYONLAR - 1

Değişkenleri olduğu gibi nesneleri de const olarak bildirebilirsiniz:

const Tarih dogum1( 7, 4, 1776 );

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.

55

Page 56: SINIFLAR GİRİŞ

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.

56

Page 57: SINIFLAR GİRİŞ

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(); // Legaldogum1.yilBelirle( 1492 ); // Error

57

Page 58: SINIFLAR GİRİŞ

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 “composition” denir:

class KisiBilgisi { public:

// Public eleman fonksiyonlar... private:

char isim[30];char adres[60];Tarih dogumTarihi;

};

dogumTarihi nesnesi KisiBilgisi sınıfından bir nesne yaratilincaya kadar yaratilmaz.

58

Page 59: SINIFLAR GİRİŞ

ELEMAN NESNELER - 2

Bir eleman nesne için yapıcı fonksiyon çağrımı, eleman nesneye ilk değer atamalarinin 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:

// ... };

59

Page 60: SINIFLAR GİRİŞ

ELEMAN NESNELER - 3

KisiBilgisi::KisiBilgisi(char *nm, char *adr, int mn, int dy, int yr):dogumTarihi( mn, dy, yr )

{ strncpy( name, nm, 30 ); strncpy( adres, adr, 60 );

}

İlk once 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.

60

Page 61: SINIFLAR GİRİŞ

Örnek #include <iostream>using namespace std;#define SIZE 100

// Stack sınıfı:class stack {

int stck[SIZE];int tos;

public:stack(); // constructor~stack(); // destructorvoid push(int i);int pop();

};

61

Page 62: SINIFLAR GİRİŞ

. . .

// Yapici Fonksiyonstack::stack(){tos = 0;cout << "Stack Initialized\n";

}

// Yikici Fonksiyonstack::~stack(){cout << "Stack Destroyed\n";}

62

Page 63: SINIFLAR GİRİŞ

. . .

void stack::push(int i){if(tos==SIZE) {

cout << "Stack is full.\n";return;

}stck[tos] = i;tos++;

}

63

Page 64: SINIFLAR GİRİŞ

. . .

int stack::pop(){if(tos==0) {cout << "Stack underflow.\n";return 0;}tos--;return stck[tos];

}

64

Page 65: SINIFLAR GİRİŞ

. . .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() << "\n";return 0;} 65

Page 66: SINIFLAR GİRİŞ

. . .

Program Çıktısı:

Stack Initialized

Stack Initialized

3 1 4 2

Stack Destroyed

Stack Destroyed

66

Page 67: SINIFLAR GİRİŞ

ÖZET Programlama dillerinin evriminde itici güç makineden uzaklaşıp probleme

yaklaşmak yönünde olmuştur. Yüksek düzeyli dillerin evrimi, algoritmik soyutlama ile başlamış, veri

soyutlaması ile devam etmiştir. İki soyutlama süreci, sınıf yapısında birleşmiştir. C++’nın sınıfları, C’nin “structure”ından türetilmiştir. Sınıflar, eleman saha ve fonksiyonlar içerirler. Sınıf elemanlarının erişim düzeyleri, etiketlerle belirlenir. Nesneler, varsa eleman sahalarına ilk değerlerin atanması için, yapıcı

fonksiyonlar ile yaratılırlar. Nesnelerin geride bıraktıklarının temizlenmesi yıkıcı fonksiyonların işidir. Sabit nesnelerin eleman sahalarının değeri değiştirilemez ve bu sahalara

yalnızca sabit oldukları bildirilmiş eleman fonksiyonlarla erişilir. Eleman nesnelerin yapıcı fonksiyonları, elemanı oldukları nesnenin yapıcı

fonksiyonunun çağrılmasından hemen önce çağrılır.

67

Page 68: SINIFLAR GİRİŞ

Kaynaklar

Booch, G. 1998. Object-Oriented Analysis and Design. Addison-Wesley.

Programmer’s Guides, Microsoft Visual C++. Wegner, P. 1976. IEEE Transactions on

Computers, December, 1207-1225.

68