Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[C++] typeinfo / typeid nie działa poprawnie

Ostatnio zmodyfikowano 2014-06-21 21:26
Autor Wiadomość
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
C/C++
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
C/C++
void Player::UseItem( Vector2i & mouse )
{
    if( m_slots[ spell ] != NULL )
    {
        if( m_slots[ spell ]->CanUse() )
        {
            cout << typeid( * m_slots[ spell ] ).name() << endl; //tu jest "problem"
           
            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)
P-112378
Monika90
» 2014-06-20 15:42:39
Czy klasa Item ma jakąś funkcję wirtualną? Bez funkcji wirtualnych to nie zadziała.
P-112383
colorgreen19
Temat założony przez niniejszego użytkownika
» 2014-06-20 15:51:07
nie ma. czyli musze stworzyć "wymuszoną" taka funkcje?
P-112384
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
P-112385
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?
P-112389
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.

C/C++
ItemAmmo * tmp_ammo = dynamic_cast < ItemAmmo *>( m_slots[ spell ] );
if( tmp_ammo )
     skill = tmp_ammo->GetAmmo();


i wywal wszędzie użycie typeid.
P-112390
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
P-112402
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:

C/C++
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; };
};
P-112403
« 1 » 2
  Strona 1 z 2 Następna strona