[]

Bir C++ sorusu.

Bir base class'ım var ve ondan inherit eden farklı classlarım var. Bu classlardan instanceları dinamik olarak yaratmak, bir vector içinde saklamak, ve daha sonra vector içinden bunlara ulaşıp üye fonksiyonlarını çağırmak istiyorum.
-----------

Mesela şöyle diyeyim, ana sınıfım "heyvan", inherit eden sınıflarım sıpa, manda, domuz.

Bir vektör içinde bir sürü sıpa-manda-domuz pointerlarını saklıyorum. Şimdi vector elemanlarını baştan sona tarayıp, pointerların point ettiği objelerin üye fonksiyonlarını çağıracağım bir loop içinde.

Diyelim ki vektörün ilk elemanı olan pointerı aldım, bunu dereference ettim, şimdi doğru tipe(sıpa mı, manda mı, domuz mu) cast etmem gerekiyor.

Ama point edilen objenin tipini nasıl bulacağım?

Sanıyorum ki "typeid" bunun için var. Basitçe biri açıklayabilir mi nasıl kullanıldığını?

Teşekkürler

 
Sanırım heyvan'a cast edersen sorun olmayacaktır. Denedin mi? Ben denemedim :)


  • fredi  (02.05.08 01:03:47) 
Hmm denemedim ama pek olabilir gibi de gelmedi. heyvanda bulunmayan değişkenler, üye fonksiyonlar falan olacak sonuçta hangisine eriştiğimi anlayaak mekanizma nereden gelecek?

Ya da diyelim ki vektörde farklı tip objeler var o zaman ne yapacağız? Belki daha iyi bir yöntem bulunabilir ama yine de bir yolu vardır diey tahmin ediyorum.
  • kurukafa  (02.05.08 01:09:56) 
onun nasıl kullanıldığını açıklarım ama dizaynında bir hata var gibi şöyle ki;

sen vektorden ilk elemanı aldın, hayvan* şeklinde sonra bir iş yapacaksın, bu iş öyle bir iş ki , sıpa manda ve domuz için ayrı ayrı tanımlı yani şöyle;

switch (type)
case manda:
mandaicinyap(ptr)
case sipa:
sipaicinyap...
case domuz:
domuzicinyap..

gibi. bunu yapmanın daha kolay yolu ise yine virtual method kullanmak. yani burdaki her bir case in içinde yapılan işi, kendi class ı içinde aynı isimle virtual function olarak tanımlarsan tipi dinamik olarak öğrenme gereksinimin kalkabilir.

yani şöyle bir yapı seni kurtarabilir;

class hayvan
{
virtual void func()=0;
}

class manda
{
virtual void func()
{mandaicinyap(this);} //üstteki switch içindeki fonksyon
}


class sipa
{
virtual void func()
{sipaicinyap(this);}
}

class domuz
{
virtual void func()
{domuzicinyap(this);}
}


//switch case yerine de bu alttaki;
foreach(ptr in vector) //foreach yok tabi built-in
ptr->func();


typeid içinse şöyle olcek;

hayvan *ptr=v[0];
if (typeid(*ptr)==typeid(sipa))
//...sipaiçin
else if (typeid(*ptr)==typeid(domuz))
//...domuzçin
else if (typeid(*ptr)==typeid(manda))
//...mandaiçin

ayrica vectorde pointer taşımak biraz riskli. boost kütüphanesinde pointer container diye ayrı bir şey var. bir de bir de pointer yerine boost tan shared_ptr kullanabilirsin ki bu da seni deallocation derdinden kurtarır hafif java tadı yakalarsın.

bir de unutmadan typeid kullanmak için compiler ayarlarından rtti yi açman gerekiyor.
  • rahan  (02.05.08 01:19:23 ~ 01:32:03) 
rahan sağol aynen dediğin gibi. inherit edilmiş objectlerin instance larına base tipinde erişebileceğimizi bilmiyordum, sorun oradan kaynaklanıyormuş. sanıyorum virtual functionlar işimi görecek.


  • kurukafa  (02.05.08 02:03:02) 
cok gereksiz bir bilgi vereyim affiniza siginarak; derived classlardaki functionlarin virtual olmasina gerek yoktur diye biliyorum.

Bir de rahana bir soru yonelteyim; hocam bu boost kutuphanesini filan hangi sirkette kullaniyorsun turkiye'de cok merak ettim cidden :)
  • egotm  (02.05.08 03:11:46) 
Rahan'ın önerisini denedim ve çalışıyor. egotm'in, dediği gibi, inherited sınıflarda virtual kullanmadım.


  • kurukafa  (02.05.08 07:41:34) 
derived class da aynı isimli aynı argümanlı fonksiyona virtual demesen de virtual gibi davranması lazım zaten. kısaca oraya virtual yazıp yazmamak çok mühim değil. virtual olmasa zaten hayvan* üzerinden dispatch edilip çağrılamaz.

egotm ufak bi şirket bizimkisi zaten bi ben kullanıyorum (hatta kıl oluyorlar hafif). ayrıca böyle düzgün cpp kullanan coderlarla ihtiyacı olan şirketlere de selam ederim.
  • rahan  (02.05.08 10:55:50) 
@rahan, evet dedigin gibi sonucta bir degisiklik olmuyor ama manda dan baska bir sinif daha turetilse bu sefer fark ortaya cikar; hatta o derived class da virtual olarak tanimlanmis fonksiyon, vtable da bile yer alabilir-emin degilim-; kisaca, dynamic binding yapilirken sadece base class icin virtual keyword eklenmelidir.

@kurukafa, baska bir gereksiz ayrinti vereyim, simdi sen o programda derived typedan base type a casting yaptigin icin, base typedaki destructor in virtual olmalidir. virtual destructor-aksi taktirde memory leak i tutmus olursun :)

not: rahan la birlikte, ben de cpp i tercih eden firmalara selam cakar, anneme de buradan el sallarim.
  • egotm  (02.05.08 14:53:59) 
1
buraya yazılanların hakları Sir Anthony Hopkins'e aittir.
yazan eden compumaster, ilgilenen eden fader
modere edenler angelus, Artibir, aychovsky, baba jo, basond, compumaster, deckard, duyulmasi gerektigi kadar, fader, fraise, groove salad, kahvegibi, kaymaktutmayansicaksut, kibritsuyu, monstro, pandispanya, robin, ron dennis
bu sitede yazılanların hiçbiri doğru değildir. site içeriği küçükler için sakıncalı olabilir. yazılardan yazarları sorumludur. kaynak göstermeden alıntılanamaz. devlet tarafından atanmış bir kurumun internet üzerinde kimin hangi bilgiye ulaşıp ulaşamayacağına karar vermesi insan haklarına aykırıdır. web siteleri kullanıcıların istekleri doğrultusunda bağlandıkları yerlerdir. kullanıcılar isterlerse bir web sitesine bağlanmayabilirler. bu güçleri ve imkanları mevcuttur. bir kullanıcı bir siteye bağlanmak istiyorsa bu onun tercihi ve hakkıdır. bağlanmak istemiyorsa bu yine onun tercihi ve hakkıdır. halkın kendisine hizmet etmesi için görevlendirdiği kurumlar hadlerini aşıp halka neye ulaşıp ulaşmayacağını bilmeyen cahil cühela muamelesi edemezler. ebeveynlerin çocuklarını sakıncalı içeriklerden koruması için çok sayıda bedava ve ücretli yazılım mevcuttur. bu yazılımlar bir web tarayıcısını kullanmaktan daha karmaşık teknik bilgi gerektirmemektedir. devletin milletini küçük düşürmesi ve ebleh yerine koyması yasaktır. Skimlinks ile linkler üzerinden yönlendirme payı alınmaktadır.