Tür Dönüştürme Operatörleri

C programlama dilinde tür dönüştürme sadece bir tane “cast”(tür dönüştürme) operatörüyle  kolaylıkla yapılabiliyordu. Örneğin;


int a = 5;

short b = (short) a; // operator() burda tür dönüştürme operatörü olarak kullanılıyor

C++ da ise durum biraz daha farklı. Tür dönüştürme işlemi biraz daha detaylı olarak ele alınmış. Şöyleki tür dönüştürme işlemini neyi amaçlıyorsanız o amaca uygun tür dönüştürme operatörünü kullanmalısınız. Şimdi tek tek bu operatörleri inceleyelim.

dynamic_cast (dinamik tür dönüştürme operatörü):

Referanslar ve göstericiler için kullanılır. Geri dönüş değeri istenilen türe dönüştürme işlemi başarısız ise NULL’dır. Genel kullanım alanlarından biri çalışma zamanında tür belirlenmesi (Run Time Type Identification) içindir. Örnek kod üzerinden ilerlersek:


#include <iostream>

using namespace std;

class Hayvan
{

public:

    virtual void turIsmi(){cout << "Tür ismi: Hayvan" << endl;};
};

class Aslan: public Hayvan
{
public:
    virtual void turIsmi() {cout << "Tür ismi: Aslan" << endl;};

};

int main(int argc, char** argv)
{
    Hayvan *h1 = new Hayvan();
    Hayvan *h2 = new Aslan(); //burda aslında gizli bir tür dönüştürme işlemi var. Yine burda da dynamic_cast operatörü kullanılabilir.
    Hayvan *h3;

    if ((h3 = dynamic_cast<Aslan*>(h1)) == NULL)
        cout << "h1 Aslan türüne dönüştürülemez." << endl;

    if ((h3 = dynamic_cast<Aslan*>(h2)) == NULL)
        cout << "h2 Aslan türüne dönüştürülemez" << endl;

    h3->turIsmi();

    delete(h1);
    delete(h2);

  return 0;
}

Görüldüğü üzere Hayvan ve Aslan türünden birer nesne dinamik olarak oluşturuluyor. Daha sonra bu nesneler
Hayvan* türünden bir göstericiye atanıyor.Eğer neden Aslan* türünden bir nesne nasıl oluyorda Hayvan* türüne atanıyor diye sorarsanız dilin tasarımından dolayı diye cevaplandırırım. Kaldı ki bu tasarım daha öncede dediğim gibi çalışma zamanında tür belirlememize olanak sağlıyor. Bunun en geniş örneklerini GUI programlamada görebilirsiniz. Neyse konumuza geri dönelim.

Daha sonra ise dynamic_cast operatörüyle bu göstericiler Hayvan* türüne dönüştürülmeye çalışılmış tabi ki bunlardan h1 göstericisi Hayvan türüne ait bir gösterici olduğundan dynamic_cast operatörü NULL dönecektir.

h2 göstericisi(pointer) ise Aslan türünü gösterdiği için tür ödnüştürme işlemi başarılı bir şekilde gerçekleşecek. Ve 32.satırda çağırılan fonksiyon Aslan sınıfına ait olan sanal fonksiyondur.Böylelikle ekrana

Tür ismi: Aslan

yazılacaktır. Eğer burda göstericiler yerine referanslarla işlem yapsaydık başarısızlık durumunda dynamic_cast operatörü bad_cast türünden bir kural dışı nesnesi (exception) fırlatacaktır.

static_cast operatörü:
static_cast te dynamic_cast te olduğu gibi dinamiklik söz konusu değildir. Yani çalışma zamanında türün dönüşüp dönüşemediğini belirleyemezsiniz. Dolayısıyla static_cast’te tüm sorumluluk programcıya aittir. Örneğin:

class Hayvan
{

public:

void turIsmi(){cout << "Tür ismi: Hayvan" << endl;};
};

class Aslan: public Hayvan
{
public:
void turIsmi() {cout << "Tür ismi: Aslan" << endl;};

};

int main(int argc, char** argv)
{
Hayvan *h1 = new Hayvan();
Hayvan *h2 = new Aslan();

Aslan *h3;

h3 = static_cast<Aslan*>(h1);

h3->turIsmi();
delete(h1);
delete(h2);

return 0;
}

static_cast operatörüyle Hayvan* türünden bir nesne Aslan*’a dönüştürülerek yine Aslan* türünden bir göstericiye atanmıştır.
Çalışma zamanında bu kodun ne yapacağı belirsizdir(ambiguity). Bunun haricinde bu operatörle derleyici tarafından gizli(implicit)
bir şekilde yapılan tüm tür dönüştürmelerini de yapabilirsiniz.

reinterpret_cast:

Her türlü gösterici türünü  her türlü  gösterici türüne çevirebilir. Bilinçsiz kullanımı kesinlikle tavsiye edilmez. Aslında basit olarak
göstericinin diğer göstericiye binary olarak kopyalanmasıdır. Hash fonksiyonlarında pratiklik açısından adres olarak kullanılan alanı hash değerine çevirmek için kullanılır. Kullanım alanları oldukça kısıtlıdır. Örneğin;


#include <iostream>

using namespace std;

int main()
{
int a = 5;

unsigned int *b = reinterpret_cast<unsigned int*>(&a + 1);

cout << *b << endl;

return 0;
}

const_cast:

Bir türün değişmezliğini manipüle etmemizi sağlar. Örneğin:


#include <iostream>

using namespace std;

void printf(char *p)
{
cout << "char * " << p << endl;
}

int main(int argc, char** argv)
{
const char *s = "islam yasar";

char *p = const_cast<char*>(s);

printf(p);

return 0;
}

Görüldüğü üzere const olan bir nesnenin normalde const olmayan bir nesneye atanması mümkün değil. Bu tür dönüştürme operatörü ile mümkün hale geliyor.

NOT:

Madem çalışma zamanında tür belirlemeden bahsettik typeid operatörünü de araya sıkıştıralım.

typeid:

bu operatör basitçe çalışma zamanında gelen nesnenin türünü belirlememizi sağlıyor. Daha önce bunu dynamic_cast operatörüyle yapmıştık.


Hayvan *h1 = new Hayvan();
Aslan *h2 = new Aslan();

if (typeid(h1) == typeid(Aslan*))
cout << "h1 Aslan* türünden" << endl;

if (typeid(h2) == typeid(Aslan*))
cout << "h2 Aslan* türünden" << endl;

İslam Yaşar

Advertisements

One thought on “Tür Dönüştürme Operatörleri

  1. Küçük bir tavsiye; sahaya sürülecek üründe dynamic cast mümkün olduğunca kullanmamak gerekir. Debug yaparken dynamic cast kullanırken ürünün sonunda bunları static castlere çevirmek performans için iyi olacaktır . Özellikle multiple inheritence varsa dynamic cast perf. sorunlarına sebeb olacaktır .

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s