[C++] typeinfo / typeid nie działa poprawnie
Ostatnio zmodyfikowano 2014-06-21 21:26
colorgreen19 Temat założony przez niniejszego użytkownika |
[C++] typeinfo / typeid nie działa poprawnie » 2014-06-20 14:59:19 Witam, moze najpierw troche opisze: W classie Player mam tablice wskaźników na item (jest to "podręczny wybor itemów") Item * m_slots[ 6 ]; .Kazdy wskaznik w niej jest ustawiany na NULL w konstrkutorze. W konstruktorze pochodnym przypisuje pewne itemki do tej tablicy spell = First; Item * l_item; l_item = new ItemAmmoWizardBasic; m_slots[ 0 ] = l_item; Items.push_back( l_item );
l_item = new ItemAmmoWizardExplosion; m_slots[ 1 ] = l_item; Items.push_back( l_item ); l_item = NULL;
gdzie spell to obiekt enum Spell { First, Second, Third, Fourth, Fifth, Sixth }; (wskazuje ktory item jest wybrany). I teraz kiedy w grze naciskam LPM ma byc uzyty item (jezli to możliwe) z danego slotu void Player::UseItem( Vector2i & mouse ) { if( m_slots[ spell ] != NULL ) { if( m_slots[ spell ]->CanUse() ) { cout << typeid( * m_slots[ spell ] ).name() << endl; if( typeid( * m_slots[ spell ] ) == typeid( ItemBuff ) ) { } else if( typeid( * m_slots[ spell ] ) == typeid( ItemAmmo ) ) { if( m_AllowToAttack ) { float a =( mouse.x ) -( m_positionX + 16 ); float b =( mouse.y ) -( m_positionY + 32 ); float angle =( atan2( a, b ) * 180 / PI ) * - 1; Ammo * skill = NULL; ItemAmmo * tmp_ammo = reinterpret_cast < ItemAmmo *>( m_slots[ spell ] ); skill = tmp_ammo->GetAmmo(); } } } } }
zaznaczona linijka "tu jest problem" wyswietla ze znajduje sie tam Item a nie jak powinno byc ItemAmmoWizardBasic bo przeciez tak to ustwialismy wczesniej. Jakieś pomysły czemu tak sie dzieje. PS: czy to rzutowanie ktore tam poźniej robie moze być jakoś którtsze albo coś, czy w ogole dobrze to wykonuje? (chociaż poznam to rozwiązanie jak rozwiąrze pierwszy problem) |
|
Monika90 |
» 2014-06-20 15:42:39 Czy klasa Item ma jakąś funkcję wirtualną? Bez funkcji wirtualnych to nie zadziała. |
|
colorgreen19 Temat założony przez niniejszego użytkownika |
» 2014-06-20 15:51:07 nie ma. czyli musze stworzyć "wymuszoną" taka funkcje? |
|
Monika90 |
» 2014-06-20 15:54:48 Dodaj destruktor wirtualny, on i tak jest potrzebny by mozna było usunąć itemy za pomocą delete.
Jak już to zrobisz to nie używaj typeid + reinterpret_cast, używaj dynamic_cast |
|
colorgreen19 Temat założony przez niniejszego użytkownika |
» 2014-06-20 16:27:52 ten destruktor virtualny wystarczy dla bazowego Item, tak? czy jesczze podefiniowac zwykłe w pochodnych klasach i jeszcze bo jest warunek else if( typeid( * m_slots[ spell ] ) == typeid( ItemAmmo ) ) to jak podstawimy to bedzie else if( typeid( ItemAmmoWizardBasic ) == typeid( ItemAmmo ) ) no a wiadomo to nie jest rowne. Jak moge zrobic ze dla pochodnych od ItemAmmo warunek bedzie prawdziwy? |
|
DejaVu |
» 2014-06-20 16:31:10 Wystarczy w klasie bazowej zdefiniować destruktor wirtualny. Destruktory w klasach potomnych niejawnie zostaną uznane za wirtualne.
/edit:
Użyj dynamic_cast-a tak jak Monika90 Ci zasugerowała.
ItemAmmo * tmp_ammo = dynamic_cast < ItemAmmo *>( m_slots[ spell ] ); if( tmp_ammo ) skill = tmp_ammo->GetAmmo();
i wywal wszędzie użycie typeid. |
|
colorgreen19 Temat założony przez niniejszego użytkownika |
» 2014-06-20 19:49:52 tylko ze niektóre itemy nie tylko beda typu ItemAmmo ale takze np ItemBuff. ItemAmmo ma funkcje Ammo * GetAmmo() { return m_ammo; }; natomiast ItemBuff ma "odpowiednik" Buff * GetBuff() { return m_buff; } Te funkcje nie mogą byc wirtualne bo zwracaja inne typy wiec musze przerzutować wskaźnik na odpowiedni typ, zeby móc te funkcje wywołać. a zeby przerzutować wskaźnik na odpowidni typ to musze najpierw wiedzieć na co. Wiec ponawiam tamto pytanie, chyba ze macie jakies inne pomysły rozwiązania tego problemu |
|
DejaVu |
» 2014-06-20 19:56:43 Rzutujesz za pomocą dynamic_cast. Jeżeli wynikiem rzutowania jest wskaźnik, którego wartość wynosi NULL (lub nullptr wg C++11) to znaczy, że obiekt nie jest tego typu na który wykonywałeś rzutowanie. /edit: alternatywnie: class KlasaB; class KlasaC;
class KlasaA { public: virtual ~KlasaA() { }; virtual KlasaB * dajKlaseB() { return nullptr; }; virtual KlasaC * dajKlaseC() { return nullptr; }; };
class KlasaB : public KlasaA { KlasaB * dajKlaseB() override { return this; }; };
class KlasaC : public KlasaA { KlasaC * dajKlaseC() override { return this; }; }; |
|
« 1 » 2 |