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
    uLtRaLoVeR
    uLtRaLoVeR's avatar
    Kayıt Tarihi: 25/Haziran/2007
    Erkek
    Waze bunu yazdı

    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.

    Bahsettiğim şey bundan çok farklı değildi. update methodunu çağırırken cast edip çağırırsan virtual olmasına gerek kalmaz. Ama dediğim gibi entity sınıfının tüm alt sınıflarını bilmesi lazım. Bu da nesneye yönelik tasarım ilkelerine aykırı. Aslında şuanki çözümün de bu ilkelere aykırı oluyor. Çünkü farklı bir entity türü eklemek istediğinde alakasız yerlerin kodunu değiştirmen gerekecek. Akılcılık konusuna gelince bence virtual yaparak direk entity'nin update'ini çağırmak ve gerçek türünün ne olduğuna onun karar vermesini sağlamak daha akılcı.

     

     

    uLtRaLoVeR tarafından 19/Kas/15 02:33 tarihinde düzenlenmiştir
  2. KısayolKısayol reportŞikayet pmÖzel Mesaj
    Waze
    Waze's avatar
    Kayıt Tarihi: 01/Ekim/2012
    Erkek
    uLtRaLoVeR bunu yazdı
    Waze bunu yazdı

    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.

    Bahsettiğim şey bundan çok farklı değildi. update methodunu çağırırken cast edip çağırırsan virtual olmasına gerek kalmaz. Ama dediğim gibi entity sınıfının tüm alt sınıflarını bilmesi lazım. Bu da nesneye yönelik tasarım ilkelerine aykırı. Aslında şuanki çözümün de bu ilkelere aykırı oluyor. Çünkü farklı bir entity türü eklemek istediğinde alakasız yerlerin kodunu değiştirmen gerekecek. Akılcılık konusuna gelince bence virtual yaparak direk entity'nin update'ini çağırmak ve gerçek türünün ne olduğuna onun karar vermesini sağlamak daha akılcı.

     

     

    Onun için nasıl bir yol önerirsin hocam, update methodu geriye kendi tipini döndürse nasıl olur?

    Edit: Gerçi o da olmaz, player'ı almak istediğimde update çağırırsam çarşı karışır.

    Waze tarafından 19/Kas/15 04:17 tarihinde düzenlenmiştir
  3. KısayolKısayol reportŞikayet pmÖzel Mesaj
    YeniHarman
    YeniHarman's avatar
    Kayıt Tarihi: 17/Haziran/2012
    Erkek

    Nasıl bir şeye ihtiyacın olduğunu bir yazsana. Örneğin X, Y, Z sınıfları olacak, T jenerik listede tutulacak. X, Y -> a, b, c metotlarına; Z ise c, e metotlarına sahip olacak gibi.

    Örneğin ortak metot c ve hepsinde ortak bir şey döndürüyorsa base'in c metodu olmalı. X ve Y base'in deliveredından türetilmeli. Z ise base'den kalıtım alarak e methoduna sahip olmalı gibi. Bu metotların özelliğine göre de (hepsinin uyarlaması farklı ya da değil) virtuallığı belirlenecek.


    Olaylara karışmayın!
  4. KısayolKısayol reportŞikayet pmÖzel Mesaj
    NmC
    NmC's avatar
    Kayıt Tarihi: 23/Kasım/2008
    Erkek
    uLtRaLoVeR bunu yazdı
    Waze bunu yazdı

    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.

    Bahsettiğim şey bundan çok farklı değildi. update methodunu çağırırken cast edip çağırırsan virtual olmasına gerek kalmaz. Ama dediğim gibi entity sınıfının tüm alt sınıflarını bilmesi lazım. Bu da nesneye yönelik tasarım ilkelerine aykırı. Aslında şuanki çözümün de bu ilkelere aykırı oluyor. Çünkü farklı bir entity türü eklemek istediğinde alakasız yerlerin kodunu değiştirmen gerekecek. Akılcılık konusuna gelince bence virtual yaparak direk entity'nin update'ini çağırmak ve gerçek türünün ne olduğuna onun karar vermesini sağlamak daha akılcı.

     

     

    Hocam aslında yapıyı bozmuyor şu an. Entity Manager dediği class içerisinde yapıyor bunu. Ve 1vsAll durumu söz konusu. Diğerlerinin tiplerini bilmesine gerek yok, sadece içlerinden bir veya birkaçı Player tipinde ise onlara ekstra bir muamelede bulunuyor :) Yeni bir entity türü Player gibi ekstra bir muamele görmeyecekse ekstra kod eklemesini gerektiren bir durum yok :)


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

    Hocam aslında yapıyı bozmuyor şu an. Entity Manager dediği class içerisinde yapıyor bunu. Ve 1vsAll durumu söz konusu. Diğerlerinin tiplerini bilmesine gerek yok, sadece içlerinden bir veya birkaçı Player tipinde ise onlara ekstra bir muamelede bulunuyor :) Yeni bir entity türü Player gibi ekstra bir muamele görmeyecekse ekstra kod eklemesini gerektiren bir durum yok :)

    Virtual kullanmadan yapmak isterse önce entity vectorunden pointer'ları alıp sırayla player'a cast etmeyi deneyecek. Eğer cast başarılı olursa onun, olmazsa önceki halinin update fonksiyonunu çağıracak. Buraya kadar hem fikiriz sanırım. Şimdi bir de farklı bir entity ekleyelim. Stoper olsun o da. Entity manager içerisindeki bu döngünün içine bir de stoper'e cast etmeyi denemeyi eklemek zorundayız bundan bahsettim ben. Entity classının değil, entity manager'ın tüm entity türlerinden haberi olması gerekiyor bu durumda. Önceki yorumda o kısmı yanlış belirtmişim. Ama bana yine de mantıksız geliyor. Entity manager olaya daha soyut bi şekilde, doğrudan entity diyerek bakmalı bence, alt sınıfını bilmeden.

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

    Hocam aslında yapıyı bozmuyor şu an. Entity Manager dediği class içerisinde yapıyor bunu. Ve 1vsAll durumu söz konusu. Diğerlerinin tiplerini bilmesine gerek yok, sadece içlerinden bir veya birkaçı Player tipinde ise onlara ekstra bir muamelede bulunuyor :) Yeni bir entity türü Player gibi ekstra bir muamele görmeyecekse ekstra kod eklemesini gerektiren bir durum yok :)

    Virtual kullanmadan yapmak isterse önce entity vectorunden pointer'ları alıp sırayla player'a cast etmeyi deneyecek. Eğer cast başarılı olursa onun, olmazsa önceki halinin update fonksiyonunu çağıracak. Buraya kadar hem fikiriz sanırım. Şimdi bir de farklı bir entity ekleyelim. Stoper olsun o da. Entity manager içerisindeki bu döngünün içine bir de stoper'e cast etmeyi denemeyi eklemek zorundayız bundan bahsettim ben. Entity classının değil, entity manager'ın tüm entity türlerinden haberi olması gerekiyor bu durumda. Önceki yorumda o kısmı yanlış belirtmişim. Ama bana yine de mantıksız geliyor. Entity manager olaya daha soyut bi şekilde, doğrudan entity diyerek bakmalı bence, alt sınıfını bilmeden.

    Hocam olayı şöyle düşün. Arkadaşın örneği üzerinden gidecek olursak. Bir oyun sahnesinde game objectler var. Ve bunları tutan bir game object vectoru var. Her bir objenin yeni pozisyonunu gameobject->update üzerinden çağırırız. Fakat sahne render edilirken en son olarak sahneye bakış açımızı (kamerayı) player gözünden yapmamız gerektiği için game objeler içerisinden player'ı bulup ona göre sahne açısını değiştirebiliriz. Bu gibi durumlarda yardımcı olacaktır bu yaklaşım. Adam player'ı update fonksiyonunu çağırmak için değil. Player'ın kordinatını almak için kullanacak sadece, öyle düşünebilirsin. Fonksiyon gene virtual kalacak yani.


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

    YeniHarman hocam tam olarak NmC hocamın bahsettiği şeyi yapmaya çalışıyorum.

    Aslında herşeyi baştan bir anlatmak gerekirse;

    Ekrana basmam gereken resimleri Sprite sınıfında tutuyorum. İçinde render methodu var. (render'ı entity'de mi sprite'ta mı yapmam gerekir sizce)
    EntityManager sınıfında vector<Entity*> var. Adı entities.
    Entity sınıfında x, y, w, h gibi standart bilgiler var. Bir de Sprite nesnesi var içinde, her varlığın bir resmi olmak zorunda.
    Player sınıfı Entity'den miras alıyor. Extra olarak zıplama, hareket etme methodları var.

    Tüm Entity'ler ile beraber Player da entities listesinde tutuluyor.
    1 - Önce Player'ın update methodunu çalıştıramıyordum, dediğiniz gibi virtual yapınca ortadan kalktı sorun.
    2 - Entities içinden istediğim zaman Player bilgilerine ulaşmam gerekiyordu, o da dediğiniz gibi dynamic_cast ile halloldu.

    Şimdi, yeni bir sorun var.
    1 - Bir tane Camera sınıfım var. İçinde  Vector2 position (x, y) bir de Uint8 zoomRatio  var.
    2 - Entity içinde bir SDL_Rect, mutlak pozisyon ve boyut bilgilerini tutuyor. (x, y, w, h) şeklinde. (ismi rect)
    3 - Göreceli pozisyon ve boyutları üretmek için Entity içinde GetX, GetY, GetWidth, GetHeight fonksiyonları var. Bu fonksiyonların hepsi parametre olarak Camera* alıyor.
    4 - GetX ve GetY fonksiyonları sırayla { rect.x + camera->position.x } ve { rect.y + camera->position.y } bilgilerini return ediyor.
    5 - GetWidth ve GetHeight sırayla { rect.w * camera->zoomRatio } ve { rect.h * camera->zoomRatio } bilgilerini return ediyor.

    Buraya kadar sorun yok.

    1. Entity'nin Render methoduna bir Camera* veriliyor.
    2. Bu method aynı kamerayı GetRect methoduna (ki bu az önceki 4 methodun yaptığı işi yapıyor) gönderip sonucu Sprite->Render methoduna parametre olarak veriyor.3. Son olarak Sprite->Render içinde, Sprite içindeki SDL_Texture nesnesi SDL_RenderCopyEx fonksiyonu ile ekrana basılıyor.

    Buraya kadar da sorun yok. Camera'yı geçiçi bir kod yazıp ok tuşlarıyla oynattığımda sorun görmedim.

    Sorun şu:

    Camera'nın Player'ı takip etmesi gerekiyor. EntityManager Update methodu (tüm entity'leri update eden method) içinde Player'ın pozisyonunu alıp Camera'nınkine eşitliyorum.
    Ama Entity render edilirken GetRect methodu ile Camera offsetlerini zaten eklemiştik.
    Böylece camera her player'a yaklaştığında player daha uzaklaşıyor.

    Derken aklıma bir fikir geldi. Entity GetAbsolutePosition diye ayrı bir fonksiyon yazdım.Sonra dönen değerin negatifini alıp camera->position'a eşitledim. Oldu.

    Vay be sorunu anlatayım derken kendi kendime rubber duck yaptım. :P

    Tekrar teşekkürler yardımlarınız için.

    Gider ayak bi soru daha sorayım:

    Entity.h içinde #include Camera.h var.
    Camera.h içinde Entity* followingEntity tanımlamak istediğimde Entity tanımlı değil diyor. Oysa ki #include Entity.h yaptım.
    Böyle çapraz include yapınca sorun mu oluyor?

     

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

    2-3 mesaj önce yazdığım Forward declaration  konusuna bak hocam :)


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

    Çarpraz includeler sorun çıkarır. include koruması koymalısınız ya da pragma once kullanmak lazım.

    Include koruması 

    .h dosyası içine asd.h olsun

    #ifndef ASD_H

    #define ASD_H

    /* h. dosyası içeriği 

    .....

    ....

    */

    #endif

     

    Bu arada player nesnesi zaten bir tane değil mi? vectorün içinde zaten referansı tutuluyor. Başka bir yerde daha bu referansı tutarsan sorun kalmaz çünkü gerçekten ulaşman gerektiğinde player'ı bulursun ve cast yapmana gerek kalmaz :)

    Ben olsam entityleri playerdan tamamen soyutlarım (playerın entitysi sabit kalarak). Oyuncu nesnem, oyuncunun görebileceği tüm entityleri kendisi saklar.


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

    Çarpraz includeler sorun çıkarır. include koruması koymalısınız ya da pragma once kullanmak lazım.

    Include koruması 

    .h dosyası içine asd.h olsun

    #ifndef ASD_H

    #define ASD_H

    /* h. dosyası içeriği 

    .....

    ....

    */

    #endif

     

    Bu arada player nesnesi zaten bir tane değil mi? vectorün içinde zaten referansı tutuluyor. Başka bir yerde daha bu referansı tutarsan sorun kalmaz çünkü gerçekten ulaşman gerektiğinde player'ı bulursun ve cast yapmana gerek kalmaz :)

    Ben olsam entityleri playerdan tamamen soyutlarım (playerın entitysi sabit kalarak). Oyuncu nesnem, oyuncunun görebileceği tüm entityleri kendisi saklar.

    Defineleri zaten koyuyorum hocam. Pragma'yı aşağıdaki gibi yaptım bir yanlışlık mı var?
    #pragma once
    #ifndef CAMERA_H
    #define CAMERA_H
    ....

    #endif

    Oyuncu'yu ayırmak istemiyorum çünkü önceden dediğim gibi update, render vs. yapmak için ayrı ayrı kod yazmak kötü bir yol gibi geliyor. EntityManager içinde bir referansı olması en iyi yol sanırım.

    NmC bunu yazdı

    2-3 mesaj önce yazdığım Forward declaration  konusuna bak hocam :)

    Hocam mesajı okuyunca bakmıştım da açıkçası birşey anlayamadım ingilizcem çok iyi değil. :)

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