folder Tahribat.com Forumları
linefolder C - C++
linefolder Std::Vector<Object> İçinde Derived Object Kullanmak



Std::Vector<Object> İçinde Derived Object Kullanmak

  1. KısayolKısayol reportŞikayet pmÖzel Mesaj
    Waze
    Waze's avatar
    Kayıt Tarihi: 01/Ekim/2012
    Erkek

    Biliyorum çok sık soru sordum ama kusura bakmayın. Normalde ilk google'a sorarım ama bu sorunu nasıl arayacağımı bilemedim...

    Bi tane vector var ve içinde Entity türünden nesneler var.
    std::vector <Entity*> entities;



    Bir tane de yine Entity'den türeyen Player sınıfı/nesnesi var.

    Player* player = new Player(renderer);
    Add(player); // entities içine ekliyor



    Bir döngü yardımıyla entities içindeki tüm nesneleri gezip hepsinin update methodunu çalıştırıyorum.

    for (size_t i = 0; i < entities.size(); i++) {                                                                                   
        entities[i]->Update(_keyboardState, _gravity); // parametreler yukardan geliyor
    }

     

    Normalde Player sınıfında Entity'nin Update methodunu override ettim, ama vector içine atınca Player'a Entity muamelesi yapıyor. Entity'nin Update methodunu çalıştırıyor.
    Döngü içinde Player'a typeid yapınca Entity alıyorum.

    Sebebi ne olabilir?

  2. KısayolKısayol reportŞikayet pmÖzel Mesaj
    NmC
    NmC's avatar
    Kayıt Tarihi: 23/Kasım/2008
    Erkek

    http://www.learncpp.com/cpp-tutorial/121-pointers-and-references-to-the-base-class-of-derived-objects/

    Virtual Function ile tanış bakalım :)

     


    There are 10 types of people in the world. Those who knows binary and those who dont...
  3. KısayolKısayol reportŞikayet pmÖzel Mesaj
    YeniHarman
    YeniHarman's avatar
    Kayıt Tarihi: 17/Haziran/2012
    Erkek

    virtual bildirimini unutmuyorsunuz değil mi? Aksi halde çalışacak metodu pointer seçer. Örnek:

    #include <iostream>

    #include <vector>

    using namespace std;

     

    class Entity

    {

    private: int _i;

    private: string _name;

    public: virtual void Update(int i)

    {

    _i = i;

    }

    public: virtual int GetI()

    {

    return _i;

    }

    public: virtual void Name(string name)

    {

    _name = name;

    }

    public: virtual string Name()

    {

    return _name;

    }

    };

     

    class Player: public Entity

    {

    private: int _i;

    private: string _name;

    public: void Update(int i)

    {

    _i = i*2;

    }

    public: int GetI()

    {

    return _i;

    }

    public: void Name(string name)

    {

    _name = name;

    }

    public: string Name()

    {

    return _name;

    }

     

    };

    int main() {

    std::vector <Entity*> entities;

     

    Player * a = new Player();

    a->Name("Player a");

    a->Update(4);

    entities.push_back(a);

     

    Entity * b = new Entity();

    b->Name("Entity b");

    b->Update(3);

    entities.push_back(b);

     

    for(int i = 0; i < entities.size(); ++i)

    {

    cout << "Once " << entities[i]->Name() << " " << entities[i]->GetI() << endl;

    }

     

    for(int i = 0; i < entities.size(); ++i)

    {

    entities[i]->Update(10);

    }

     

    for(int i = 0; i < entities.size(); ++i)

    {

    cout << "Sonra " << entities[i]->Name() << " " << entities[i]->GetI() << endl;

    }

    // your code goes here

    return 0;

    }


    Olaylara karışmayın!
  4. KısayolKısayol reportŞikayet pmÖzel Mesaj
    YeniHarman
    YeniHarman's avatar
    Kayıt Tarihi: 17/Haziran/2012
    Erkek

    Bu gibi durumlarda (ortak metot sayısı azsa) interface'den kalıtım alın, aksi halde abstract bir sınıf oluşturup hepsini bundan türetin. Daha iyi bir alışkanlıktır (sonradan da genişletilebilir).


    Olaylara karışmayın!
  5. KısayolKısayol reportŞikayet pmÖzel Mesaj
    Waze
    Waze's avatar
    Kayıt Tarihi: 01/Ekim/2012
    Erkek

    Teşekkürler ikinize de, dediğiniz gibi virtual olarak tanımlayınca sorun halloldu. Döngüde de ufak bir değişiklik yapmam gerekti:

    for (std::vector<Entity*>::iterator i = entities.begin(); i != entities.end(); ++i)                                              
        (*i)->Update(_keyboardState, _gravity);
    }

    Interface işi çok uzatır da Entity'yi ya da ondan önce EntityBase falan diye bi sınıfı abstract yapabilirim. Ama şimdilik projede biraz yol almaya çalışacağım.

    Bu arada problemin adı slicing imiş:

    http://stackoverflow.com/questions/274626/what-is-object-slicing

    Tekrar teşekkürler.

  6. KısayolKısayol reportŞikayet pmÖzel Mesaj
    Waze
    Waze's avatar
    Kayıt Tarihi: 01/Ekim/2012
    Erkek

    Virtual methodu derived sınıfta tekrar yazdıktan sonra orjinal haline hala erişebilir miyiz?
    C# taki base.helloWorld() gibi?

    Çünkü methodun içini tekrar yazmak pek uygun bir yöntem gibi gelmedi. Böylece sadece eklemek istediklerimi yazarım kod fazlalığı olmaz dedim.

  7. KısayolKısayol reportŞikayet pmÖzel Mesaj
    YeniHarman
    YeniHarman's avatar
    Kayıt Tarihi: 17/Haziran/2012
    Erkek

    İşte diyorum senin çözümün abstract sınıf:)

    base'in elemanlarına (eğer erişim yetkisi varsa) miras alan sınıfta doğrudan base sınıfın isim uzayından erişilebilir. Örneğin Base::AMethod();

    Örnek: http://ideone.com/pUEmeo

    #include <iostream>

    using namespace std;

     

    class Base

    {

    public: virtual void BaseMethod()

    {

    cout << "Written by base." << endl;

    }

    };

    class Delivered : public Base

    {

    public: void BaseMethod()

    {

    Base::BaseMethod();

    cout << "Written by delivered." << endl;

    }

    };

    int main() {

    Base * base = new Base();

    Base * delivered = new Delivered();

     

    base->BaseMethod();

     

    cout << endl;

     

    delivered->BaseMethod();

    // your code goes here

    return 0;

    }


    Olaylara karışmayın!
  8. KısayolKısayol reportŞikayet pmÖzel Mesaj
    Waze
    Waze's avatar
    Kayıt Tarihi: 01/Ekim/2012
    Erkek

    Teşekkürler, tam da istediğim şey. Entity sınıfında bi kaç düzenleme ile yapabilirim sanırım.

    Sormak istediğim birşey daha var.

    Üstte bahsettiğim vector<Entity*> entities, EntityManager sınıfında bulunuyor.

    Ben EntityManager'a GetPlayer() diye bir method yazmak istiyorum. Bu method entities içinden tipi Player olan nesneyi döndürecek. Bunun için entities'i bir döngüyle dolaşıp tek tek tiplerini kontrol etmek istedim. Ama yine yukarıda dediğim gibi typeid ile tipini alınca Entity olarak görüyor. Bu sorunu nasıl aşabilirim? Kafayı yemek üzereyim...

    Player'ı entities içinden çıkarıp ayrı tanımlayarak bu sorunu aşabilirim ama bunun için de entities için yaptığım her şeyi player için de tek tek yapmam gerekiyor (update, render vs). Yapıcaksam biraz şık olsun derme çatma bi kod olmasın istiyorum. Var mı bir yolu?

    *Bir çözüm daha geldi aklıma, entity içine isPlayer diye bir bool koyarım sonra onu kontrol ederim en olmadı. Caiz midir?

    Waze tarafından 19/Kas/15 00:50 tarihinde düzenlenmiştir
  9. KısayolKısayol reportŞikayet pmÖzel Mesaj
    NmC
    NmC's avatar
    Kayıt Tarihi: 23/Kasım/2008
    Erkek
    Waze bunu yazdı

    Teşekkürler, tam da istediğim şey. Entity sınıfında bi kaç düzenleme ile yapabilirim sanırım.

    Sormak istediğim birşey daha var.

    Üstte bahsettiğim vector<Entity*> entities, EntityManager sınıfında bulunuyor.

    Ben EntityManager'a GetPlayer() diye bir method yazmak istiyorum. Bu method entities içinden tipi Player olan nesneyi döndürecek. Bunun için entities'i bir döngüyle dolaşıp tek tek tiplerini kontrol etmek istedim. Ama yine yukarıda dediğim gibi typeid ile tipini alınca Entity olarak görüyor. Bu sorunu nasıl aşabilirim? Kafayı yemek üzereyim...

    Player'ı entities içinden çıkarıp ayrı tanımlayarak bu sorunu aşabilirim ama bunun için de entities için yaptığım her şeyi player için de tek tek yapmam gerekiyor (update, render vs). Yapıcaksam biraz şık olsun derme çatma bi kod olmasın istiyorum. Var mı bir yolu?

    *Bir çözüm daha geldi aklıma, entity içine isPlayer diye bir bool koyarım sonra onu kontrol ederim en olmadı. Caiz midir?

    Normalde casting ile işi çözebilirsin hocam. Şuraya bi bak http://stackoverflow.com/questions/28002/regular-cast-vs-static-cast-vs-dynamic-cast

    Ürettiğin iki çözüm de pek caiz değil :) İlkinde kullandığın yapıyı bozuyorsun. İkincisinde sadece bir sınıf yüzünden bütün hepsine gereksiz bir fonksiyon ekleyeceksin.

    Bu arada include işlemlerin karışacak muhtemelen. (Emin değilim) Eğer böyle birşeyle karşılaşırsan Forward declaration konusuna bakman gerekecek :)


    There are 10 types of people in the world. Those who knows binary and those who dont...
  10. KısayolKısayol reportŞikayet pmÖzel Mesaj
    uLtRaLoVeR
    uLtRaLoVeR's avatar
    Kayıt Tarihi: 25/Haziran/2007
    Erkek
    NmC bunu yazdı
    Waze bunu yazdı

    Teşekkürler, tam da istediğim şey. Entity sınıfında bi kaç düzenleme ile yapabilirim sanırım.

    Sormak istediğim birşey daha var.

    Üstte bahsettiğim vector<Entity*> entities, EntityManager sınıfında bulunuyor.

    Ben EntityManager'a GetPlayer() diye bir method yazmak istiyorum. Bu method entities içinden tipi Player olan nesneyi döndürecek. Bunun için entities'i bir döngüyle dolaşıp tek tek tiplerini kontrol etmek istedim. Ama yine yukarıda dediğim gibi typeid ile tipini alınca Entity olarak görüyor. Bu sorunu nasıl aşabilirim? Kafayı yemek üzereyim...

    Player'ı entities içinden çıkarıp ayrı tanımlayarak bu sorunu aşabilirim ama bunun için de entities için yaptığım her şeyi player için de tek tek yapmam gerekiyor (update, render vs). Yapıcaksam biraz şık olsun derme çatma bi kod olmasın istiyorum. Var mı bir yolu?

    *Bir çözüm daha geldi aklıma, entity içine isPlayer diye bir bool koyarım sonra onu kontrol ederim en olmadı. Caiz midir?

    Normalde casting ile işi çözebilirsin hocam. Şuraya bi bak http://stackoverflow.com/questions/28002/regular-cast-vs-static-cast-vs-dynamic-cast

    Ürettiğin iki çözüm de pek caiz değil :) İlkinde kullandığın yapıyı bozuyorsun. İkincisinde sadece bir sınıf yüzünden bütün hepsine gereksiz bir fonksiyon ekleyeceksin.

    Bu arada include işlemlerin karışacak muhtemelen. (Emin değilim) Eğer böyle birşeyle karşılaşırsan Forward declaration konusuna bakman gerekecek :)

    casting ile ilk problem de çözülebilirdi aslında ama object oriented yazmanın bir anlamı kalmıyor o durumda.

  11. KısayolKısayol reportŞikayet pmÖzel Mesaj
    Waze
    Waze's avatar
    Kayıt Tarihi: 01/Ekim/2012
    Erkek

    NmC hocam sorunu dediğin gibi çözdüm. Öyle karışıklık falan da olmadı tek seferde çalışınca gözlerim yaşardı. :D Teşekkürler.

    for (std::vector<Entity*>::iterator i = entities.begin(); i != entities.end(); ++i)                                              
    {                                                                                                                                
        if (Player* player = dynamic_cast<Player*>((*i))) {                                                                          
            std::cout << "Player was here." << std::endl;                                                                            
        }                                                                                                                            
        else {                                                                                                                       
             std::cout << "Yet another entity." << std::endl;                                                                         
        } 

    }

    uLtRaLoVeR hocam daha akılcı bi çözüm varsa çok öğrenmek isterim.

Toplam Hit: 1227 Toplam Mesaj: 25
c++ oop polymorphism