Menü Kapat

Sanal Fonksiyonlar

Kalıtım özelliğini kullanmanın sebeplerinden biri ilişkili sınıflar arasında hiyerarşi kurmaktır. Örneğin öğrenci, çalışan, yönetici gibi sınıflar varsa bu sınıfların ortak veri elemanları insan isimli bir ana sınıfta tutulabilir.

Kalıtım kullanırken türetilmiş sınıfların ana sınıftan üye fonksiyonları kalıtırken daha özelleşmiş fonksiyonlara ihtiyacı olduğu düşünülebilir. Örneğin Insan sınıfı goster() fonksiyonunda isim ve yasini gösterip türetilmiş Ogrenci sınıfı aynı fonksiyonda bölümünü gösteriyor olabilir. Bu “overriding” olarak geçer.(Polymorphism)

C++’da override edilebilir üye fonksiyon oluşturmak için fonksiyonun başına virtual ön eki koyulmalıdır.

class Insan
{
private:
    std::string isim;
    int yas;

public:
    virtual void goster() const;///Override edilebilir fonksiyon

};

 

Kaynak kodda virtual anahtar kelimesinin kullanılmadığını unutmayın:

void Insan::goster() const{
    std::cout << isim << "," << yas << std::endl;
}

 

Sanal Fonksiyonların Override Edilmesi

Türetilmiş bir sınıf oluşturduğunuzda sanal fonksiyonların bazılarını ya da tamamını ana sınıftan override edebilirsiniz. Override yapmak zorunda da değilsiniz.

Türetilmiş sınıfta sanal bir fonksiyonu override etmek için sınıfın header sayfasında fonksiyonu tekrar tanımlamanız gerekir. Fonksiyon yapısı ana sınıftakiyle uyuşmak zorundadır. Override edilebilir bir fonksiyon olduğunu belirtmek için virtual anahtar kelimesini tekrar kullanabilirsiniz.

Polymorphism

Aşağıdaki örnek ana sınıftan Ogrenci türetilmiş sınıfına goster() fonksiyonuna override edilmesini gösterir:

class Ogrenci : public Insan
{
private:
    std::string bolum;

public:
     virtual void goster() const;     // Ana sınıftan fonksiuon override eder
    ...
};

 

Türetilmiş sınıfın kaynak kodunda override edilmiş fonksiyonun yeni versiyonu uygulanır.

void Ogrenci::goster() const{
    std::cout << bolum << std::endl;
}

 

Sanal Yıkıcı Fonksiyonlar

Eğer bir ana sınıf bir ya da daha fazla sanal fonksiyon içeriyorsa sanal yıkıcı fonksiyon da tanımlamalıdır. Örneğin Insan sınıfı için sanal yıkıcı tanımı:

class Person
{
    ...
public:
    virtual ~Person();
    ...
};

Person::~Person()
{
    // Insan nesnesi için yıkıcı kodlar.
}

 

Ana sınıfta sanal yıkıcı fonksiyon tanımlayarak, bir nesneyi sildiğinizde doğru yıkıcının çağırıldığından emin olursunuz.

Değiştirilebilirlik İlkesi

Diğer nesneye yönelik programlama dilleriyle benzer olarak C++ ana sınıf tipinde nesne oluşturup bunları türetilmiş sınıflara işaret etmeye izin verir. Belirgin bir şekilde anlatmak gerekirse; X tipindeki bir işaretçi bir X nesnesine ya da X’ten türetilmiş bir nesneye işaret edebilir. Aynı şekilde X tipindeki bir referans değişkeni başka bir X nesnesine veya X’ten türetilmiş bir nesneye referans gösterebilir.

///Ana sınıf işaretçisi aynı tipe veya türetilmiş bir sınıfa işaret edebilir
Insan* i1 = new Insan;
Insan* i2 = new Ogrenci;

///Ana sınıf referans değişkeni aynı tipe veya türetilmiş bir sınıfa referans gösterebilir
Insan& r1 = insanNesnesi;
Insan& r2 = ogrenciNesnesi;

 

Aşağıdaki örnekte işaretçi kullanımını görebilirsiniz:

///Insan tipinde, Ogrenci nesnesine işaret eden bir işaretçi oluşturulur
Insan* i = new Ogrenci;

///Sanal goster() fonksiyonu çağırılır. Burada Ogrenci sınıfının goster() fonksiyonu çağırılacaktır
///çünkü i işaretçisinin işaret ettiği tip budur.
i->goster();

 

Aynısı referans kullanımında da geçerlidir:

///Insan tipinde olup Ogrenci tipinde bir nesneye referans gösteren bir referans değişkeni oluşturulur.
Insan& r = ogrenciNesnesi;

///Sanal goster() fonksiyonu çağırılır. Burada Ogrenci sınıfının goster() fonksiyonu çağırılacaktır
///çünkü r'nin referans gösterdiği tip budur.
r.goster();

 

Bir nesneyi sildiğiniz zaman C++ derleyicisi yıkıcı fonksiyonu çağırır. Eğer yıkıcı fonksiyonu sanal olarak tanımladıysanız, çalışma mekanizması doğru nesne için doğru yıkıcı fonksiyonu çağırır.

Insan* p = new Ogrenci;

///Eğer yıkıcı fonkiyon sanal ise hangi
///yıkıcı fonksiyonun seçileceği bilinir. Bu örnekte
///Ogrenci yıkıcı fonksiyonu çağırılır.
delete p;

 

Saf Sanal Fonksiyonlar ve Soyut Sınıflar

Saf sanal fonkiyonlar sanal fonksiyonlarla aynı mantıkta çalışır fakat aralarında bir kaç farklılık bulunmaktadır. Öncelikle saf sanal fonksiyon tanımlamasının nasıl olduğuna bakalım:

class Insan
{
private:
    std::string isim;
    int yas;

public:
    virtual void goster() const = 0; ///Saf sanal fonksiyon bu şekilde tanımlanır.

};

 

Saf sanal fonksiyon tanımlandığı yerde gövdeye sahip olamaz yani sadece türetilmek için oluşturulur. Ayrıca saf sanal fonksiyona sahip bir ana sınıftan türetilen her sınıf bu fonksiyonu kullanmak zorundadır.

Soyut sınıf kavramı ise tüm fonksiyonları saf sanal fonksiyon olan sınıflar için kullanılır. Saf sanal fonksiyonu override etmemiş türetilmiş sınıflar soyut sınıf olmak zorundadır yani sadece saf sanal fonksiyon tanımlamalarından oluşmalıdır.

Bir yorum yazınız. Yorumlarınız bizim için değerlidir.