• Sonuç bulunamadı

C++ Dersi: Nesne Tabanlı Programlama

N/A
N/A
Protected

Academic year: 2022

Share "C++ Dersi: Nesne Tabanlı Programlama"

Copied!
23
0
0

Yükleniyor.... (view fulltext now)

Tam metin

(1)

C++ Dersi:

Nesne Tabanlı Programlama

Çiğdem Turhan Fatma Cemile Serçe

Bölüm 20: İleri Seviye Konular

(2)

İçerik

– İleri Düzey Operatör Yükleme

• Yapıcı Fonksiyonların Dönüşüm Operatörü Olarak Kullanımı

• Dönüştürme Operatör Fonksiyonu

• = Atama Operatörü

– Çoklu Miras Kullanırken Karşılaşılan Sorunlar – Arayüz Kavramı

• UML Sınıf Diyagramında Arayüz Gösterimi

• C++ Dilinde Arayüz Tanımı

– Tasarım Örüntüleri

• Tekli Tasarım Örüntüsü

• Strateji Tasarım Örüntüsü

(3)

İleri Düzey Operatör Yükleme

• Yapıcı Fonksiyonların Dönüşüm Operatörü Olarak Kullanımı

• Bir sınıfa ait bir nesne, çeşitli tiplerdeki nesne ya da değerlerle bir operatör işlemine girecek ise, aynı operatörün farklı tipteki parametreler için ayrı ayrı tanımlanması gerekir.

• Bu sorunu gidermek için, çok sayıda fonksiyon yazmak yerine, yapıcı fonksiyonlar gerekli dönüşüm işlemini yapmak amacı ile dönüşüm operatörü olarak kullanılabilir.

• Örnek

(4)

// --- Zaman.h--- class Zaman

{public:

Zaman(int saat, int dakika, int saniye) {setZaman(saat,dakika,saniye);}

Zaman(long);

friend Zaman operator+

(const Zaman&, const Zaman&);

void setZaman(int saat, int dakika, int saniye);

void goruntule();

private:

int saat;

int dakika;

int saniye;

};

ÇIKTI 1:30:5 2:42:40 Dönüştürme işlemini gerçekleştirecek yapıcı fonksiyon

// --- Zaman.cpp ---

#include <iostream>

#include "Zaman.h"

using namespace std;

inline Zaman::Zaman(long t) { saniye = t % 60;

dakika = (t/60) % 60;

saat = (t/3600) % 24;

}

void Zaman::setZaman(int s, int d, int ss)

{ saat = s;

dakika = d;

saniye = ss;

}

void Zaman::goruntule() { cout<<saat<<":"<<dakika

<<":"<<saniye<<endl;

} // --- Uygulama.cpp ---

#include "Zaman.h"

Zaman operator+(const Zaman& t1, const Zaman& t2)

{ const long saat = t1.saat + t2.saat;

const long dakika = t1.dakika + t2.dakika;

const long saniye = t1.saniye + ,t2.saniye;

return Zaman(saat, dakika, saniye);

}

// --- Uygulama.cpp (devamı)--- int main()

{

Zaman t1(1,30,5);

Zaman t2 = t1 + Zaman(4355);

t1.goruntule();

t2.goruntule();

return 0;

}

(5)

Dönüştürme Operatör Fonksiyonu

• Yapıcı fonksiyonların dönüştürme operatörü olarak kullanılmalarının bazı kısıtları vardır.

– Yapıcı fonksiyonlar ile temel bir veri tipinden bir nesneye dönüşüm gerçekleştirilebilir, örneğin long’dan Zaman nesnesine.

– Ancak, herhangi bir nesnenin bir temel veri tipine dönüştürülmesi yapıcı fonksiyonlarla gerçekleştirilemez. Örneğin, Zaman tipinde bir nesne, temel veri tipi olan long’a yapıcı fonksiyonlar ile

dönüştürülemez.

• Bu amaçla dönüştürme operatör fonksiyonlarından yararlanılır.

• Bu fonksiyonlar aşağıdaki söz dizimi ile tanımlanır.

SinifAdı::operator VeriTipi (void)

burada SinifAdı ilgili sınıfı, VeriTipi dönüştürülecek veri tipini

simgeler.

(6)

// --- Zaman.h--- class Zaman

{public:

Zaman(int saat, int dakika, int saniye) {setZaman(saat,dakika,saniye);}

Zaman(long);

friend Zaman operator+

(const Zaman&, const Zaman&);

void setZaman(int saat, int dakika, int saniye);

void goruntule();

operator long(void) const;

private:

int saat;

int dakika;

int saniye;

};

ÇIKTI 5435.5 Dönüştürme operatör fonksiyonu

// --- Zaman.cpp ---

#include <iostream>

#include "Zaman.h"

using namespace std;

inline Zaman::Zaman(long t) { saniye = t % 60;

dakika = (t/60) % 60;

saat = (t/3600) % 24;

}

Zaman::operator long(void) const

{ return saat*3600L+dakika*60L+saniye;

}

void Zaman::setZaman(int s, int d, int ss)

{ saat = s;

dakika = d;

saniye = ss;

}

void Zaman::goruntule() { cout<<saat<<":"<<dakika

<<":"<<saniye<<endl;

// --- Uygulama.cpp --- }

#include "Zaman.h"

Zaman operator+(const Zaman& t1, const Zaman& t2)

{ const long saat = t1.saat + t2.saat;

const long dakika = t1.dakika + t2.dakika;

const long saniye = t1.saniye + ,t2.saniye;

return Zaman(saat, dakika, saniye);

// --- Uygulama.cpp (devamı)--- int main()

{

Zaman t1(1,30,5);

double suan = (long)t1 + 30.5;

cout<<suan<<endl;

return 0;

}

(7)

= Atama Operatörü

• Atama operatörü (=) özel bir operatör olduğu için bu operatöre yükleme yaparken farklı bir sözdizimi kullanmamız gerekir.

• Aynı sınıfa ait iki nesne arasında atama yapıldığında, tüm üyeler için atama yapılır.

• Bu amaç için derleyici tarafından aşağıdaki sözdizimine uygun olarak bir atama fonksiyonu hazır bulunmaktadır.

SınıfAdı& SınıfAdı::operator= (const SınıfAdı &)

class Nokta {

public:

Nokta& operator=(const Nokta& n) { x = n.x;

y = n. Y;

return *this;

}

private:

int x, y;

};

Atama operatörü

(8)

Çoklu Miras Kullanırken Karşılaşılan Sorunlar

• Çoklu miras yöntemi kullanırken dikkat edilmesi gereken bazı noktalar vardır.

– Ortak üst sınıflarda işlevi farklı ama ismi aynı olan

fonksiyonların tanımlı olmasıdır. Derleyici hangi üst sınıfa ait fonksiyonu çağıracağını bilemeyeceği için hata verir.

– Bir sınıfın birden fazla üst sınıftan miras alması, bu üst

sınıfların da ortak bir üst sınıflarının olması durumunda

gerçekleşir. Bu durumda en üst sınıfta tanımlı veri üyeleri,

tekrar tekrar miras olarak en alt sınıfa geçer.

(9)

Çoklu Miras Kullanırken Karşılaşılan Sorunlar...

Asistan

Ogrenci Birey

ad soyad tckimlik adres ogrenciNo Ogretmen

Birey

ad

soyad

tckimlik

adres

sicilNo

(10)

Sanal Üst Sınıflar

• Ing. Virtual base classes

• Sanal üst sınıflar kullanıldığında eğer ortak bir sınıf üst sınıf olacak ise bu sınıfa ait veri üyelerinden sadece bir kopya tutulur.

• Sanal üst sınıf tanımı aşağıdaki iki şekilde de yapılabilir.

class Ogretmen: virtual public Birey {...}

class Ogrenci: public virtual Birey {...}

• Sanal üst sınıfın kullanımında dikkat edilmesi gereken bir nokta vardır.

Normalde alt sınıfın yapıcı fonksiyonu üst sınıfın yapıcı fonksiyonunu

çağırır. Sanal üst sınıf kullanıldığında ise en alt seviyedeki sınıfın (Asistan)

dahi en üst seviyedeki sınıfın (Birey) yapıcı fonksiyonunu çağırması gerekir.

(11)
(12)

Arayüz

• Ing. Interface

• Bir arayüz sınıfı, o sınıfa ait üye fonksiyonların sadece prototiplerini içeren soyut bir sınıftır.

• Bu arayüzü uygulayan sınıfların, arayüzde belirtilen prototiplere göre fonksiyonların üzerine yazması zorunludur.

– UML sınıf diyagramında oklu kezik çizgi ile belirtilir.

implements (uygular) ya da realize anahtar kelimeleri

kullanılır.

(13)

Örnek

• Gosterilebilir bir arayüz sınıfıdır ve goster() fonksiyon prototipini tanımlar.

• Sekil sınıfı Gosterilebilir arayüzünü

gerçekleştirdiği için goster() üye fonksiyonuna sahiptir.

• Belge sınıfı benzer şekilde Gosterilebilir

arayüzünü gerçekleştirmektedir ve dolayısı ile goster() üye fonksiyonuna sahiptir.

• Sekil sınıfı içinde goster() fonksiyonunun içeriği verilemeyeceği için (çünkü şekle göre gösterim değişecektir), alt sınıflar bu fonksiyonun üzerine yazarlar. Bu nedenle Sekil sınıfında bu fonksiyon sanal fonksiyon olarak tanımlanmıştır.

• Kare ve Cizgi sınıfları Sekil sınıfı ile aralarındaki

miras ilişkisi sayesinde Gosterilebilir sınıflardır ve

goster() fonksiyonuna sahiptirler.

(14)
(15)
(16)

Tasarım Örüntüsü

• Bir yazılım tasarımında sıklıkla karşılaşılan problemlere yönelik geliştirilmiş ortak çözüm önerisi sunar.

• Bu çözüm önerileri, bir problemin nasıl çözülebileceğini tasarım ve uygulama boyutunda tanımlar.

• Bir tasarım örüntüsü, bir sınıf diyagramı ile tanımlanır ve hangi durumlarda kullanılabileceği anlatılır.

• Örnek

– Tekli Tasarım Örüntüsü (Singleton)

– Strateji Tasarım Örüntüsü

(17)

Tekli Tasarım Örüntüsü

• Bazı problemlere ait yazılım tasarımlarında, aynı sınıftan ikinci bir nesnenin yaratılmaması gereken durumlar olabilir.

• Bu tür durumlarda bu tasarım örüntüsü, aynı sınıftan sadece

tek bir nesnenin yaratılmasını garanti eden bir çözüm önerisi

sunar.

(18)

Tekli Tasarım Örüntüsü...

• Bu tasarım örüntüsünü uygulamak için aşağıdaki adımların izlenmesi gereklidir.

– Sınıfa ait yapıcı fonksiyonların private ya da protected etiketleri ile etiketlenerek dışarıdan erişimin engellenmesi,

– Sınıf içerisinde yaratılacak tek nesneyi gösterecek göstergenin private static etiket ile tanımı,

– Tek nesneye dışarıdan erişilmesini sağlayan public static üye fonksiyonun yazılması

– Kopya yapıcı fonksiyonun üzerine yazılıp boş bırakılması

(19)

//--- Butce.h --- class Butce

{

public:

static Butce* nesneAl();

void gelirEkle(float _gelir) {gelir +=_gelir;}

float gelirAl(){return gelir;}

void giderEkle(float _gider) {gider +=_gider;}

float giderAl(){return gider;}

protected:

Butce(float gelir=0, float gider=0){}

private:

static Butce* nesne;

float gelir, gider;

};

ÇIKTI

Gelir(Butce-1):2500 Gelir(Butce-2):2500 Gider(Butce-1):1200 Gider(Butce-2):1200

//--- Butce.cpp ---

#include "Butce.h"

Butce* Butce::nesne = 0;

Butce* Butce::nesneAl() {

if(nesne==0){

nesne = new Butce;

}

return nesne;

};

//--- Uygulama.cpp ---

#include "Butce.h"

#include <iostream>

using namespace std;

int main() {

Butce* butce1= Butce::nesneAl();

Butce* butce2= Butce::nesneAl();

butce1->gelirEkle(1500);

butce1->gelirEkle(1000);

butce2->giderEkle(700);

butce2->giderEkle(500);

cout<<"Gelir(Butce-1):"<<butce1->gelirAl()<<endl;

cout<<"Gelir(Butce-2):"<<butce2->gelirAl()<<endl;

cout<<"Gider(Butce-1):"<<butce1->giderAl()<<endl;

cout<<"Gider(Butce-2):"<<butce2->giderAl()<<endl;

return 0;

}

(20)

Strateji Tasarım Örüntüsü

• Bir yazılım uygulamasına ait gereksinimde, aynı işin farklı algoritma ve yöntemlerle yapılması isteniyor ve ileride yeni yöntemlerin de eklenme ihtimali var ise, çözüme ait tasarımın bu kapsamda esnek bir yapıda kurgulanması tercih edilir.

• Strateji tasarım örüntüsü bu amaçla kullanılan bir çözüm

önerisidir.

(21)

Örnek

• Ekran sınıfı alt seviyedeki Sekil, Belge, Kare ve Cizgi sınıfları ile değil, en üst seviyedeki Gosterilebilir

arayüzü ile bağlıdır. Böylelikle, Ekran sınıfı gösterilebilir olan her nesne ile çalışabilecek, yeniden

kullanılabilir bir sınıf olarak tasarlanabilmiştir. Ekran nesnesine bir Kare nesnesi gönderildiğinde kare

gösterecek, benzer şekilde Belge nesnesi gönderildiğinde belgedeki metni gösterecektir.

(22)

//--- Ekran.h ---

#include "Gosterilebilir.h"

class Ekran {

Gosterilebilir* gosterilebilirNesne;

public:

void gosterilebilirNesneAta (Gosterilebilir*);

void nesneGoster();

};

//--- Ekran.cpp---

#include "Ekran.h"

void Ekran::gosterilebilirNesneAta

(Gosterilebilir* _gosterilebilirNesne) { gosterilebilirNesne =

_gosterilebilirNesne;

}

void Ekran::nesneGoster()

{ gosterilebilirNesne->goster();

}

//--- Uygulama.cpp---

#include "Sekil.h"

#include "Kare.h"

#include "Cizgi.h"

#include "Belge.h"

#include "Ekran.h"

#include <iostream>

using namespace std;

int main() {

Kare kare(7);

Cizgi cizgi(7);

Belge belge("Merhaba");

Ekran ekran;

ekran.gosterilebilirNesneAta(&kare);

ekran.nesneGoster();

ekran.gosterilebilirNesneAta(&cizgi);

ekran.nesneGoster();

ekran.gosterilebilirNesneAta(&belge);

ekran.nesneGoster();

return 0;

}

ÇIKTI

*******

* *

* *

* *

* *

* *

*******

*******

(23)

Strateji tasarım örüntüsü

kullanılmadığı durum

Ekran sınıfı Gosterilebilir arayüzünü gerçekleştiren tüm somut sınıflara doğrudan bağlıdır ve her bir farklı sınıf için ayrı ayrı atama ve gösterme

fonksiyonları içerir. Bu durumda Ekran sınıfı yeniden kullanılabilir bir sınıf olamaz.

Referanslar

Benzer Belgeler

Yapıtın ka­ zandığı büyük başarı üzerine, Bar- tok’a birçok yeni beste ısmarlandı; sanatçı bunların ancak birkaçını çı­ karabildi ortaya, 1945 yılının

Özet: Bu araştırmada Atletizmde alt yapıda başarılı olan sporcuların büyükler kategorisi ve elit seviye- deki başarıları incelenmiş, bu alanda yapılan

Web sunucu olarak yaygın kullanımı ve hızlı performansı nedeniyle PHP dili için Apache server, JSP dili için ise Apache Tomcat kullanılmıştır... Web Uygulama

- Labial sırt bulunur ancak üst kanine göre daha az belirgindir.. - Kronun mezial yüzeyi dişin uzun aksı

 - Bukkal kretten mezial krete olan uzaklık, bukkal kretten distal krete olan uzaklıktan daha uzundur..  - Mesial kretten lingual krete olan uzaklık, distal kretten lingual

- Proksimalden bakıldığından bukkal ve lingual kontur kretleri anterior dişlere göre daha okluzal düzeydedir.. - Bukkal cuspın mesial eğimi distal eğimden kısadır (Üst

- Distal marjinal sırt mesial marjinal sırttan daha kısadır ve daha fazla servikal girinti yapar.. - Servikal çizgi bukkalden linguale hemen hemen düz

- Kökler alt birinci molara göre birbirlerine daha yakındır ve distale doğru eğimlidir. - Pulpa odasının kök uzantısı alt birinci molara kıyasla belirgin bir şekilde