简体   繁体   中英

C++ classes inheritance

I have two classes:

class CEnemy : CObject
{
protected:
    int hitPoints;
};
class COgro : public CEnemy
{
    COgro::COgro() {hitPoints = 100}
};

and in other file I have class 'CRocket', which can collide with COgro, there is it function:

void CRocket::OnCollision(CObject *collisionObject)
{
    if (typeid(*collisionObject) == typeid(COgro))
    {
        //collisionObject->hitPoints -= 10; ?? or what?
    }
}

I want to shoot 10 times to ogro before it dies. How to do this? I've already tried:

     collisionObject->hitPoints -= 10;
     (CEnemy)collisionObject->hitPoints -= 10;

but I can't compile it...how to edit this hitPoints value, but without changing '(CObject *collisionObject)'? Thx

EDIT:

//===============================================================

//------------------------------------CLASS CRocket-----------------------
class CRocket : public CObject
{
protected:
    void OnAnimate(scalar_t deltaTime);
    void OnCollision(CObject *collisionObject);
    void OnDraw(CCamera *camera);

public:

    float pitch;
    float distanceTravel;   
    CVector forward;        
    bool isExplosion;

    CTexture *explosionTex;
    CExplosion *explosion;

    CRocket();
    ~CRocket();

    void Load();
    void Unload();

};
void CRocket::OnCollision(CObject *collisionObject)
{
        if (typeid(*collisionObject) == typeid(COgroEnemy))
        {
            isExplosion = true;
            velocity = CVector(0.0, 0.0, 0.0);
            explosion = new CExplosion(500, position, 8.0, explosionTex->texID);
            PlaySound();
        }
}

//-----------------------------------------class CObject
class CObject : public CNode
{
protected:
    virtual void OnAnimate(scalar_t deltaTime)
    {
        position += velocity * deltaTime;
        velocity += acceleration * deltaTime;
    }
    virtual void OnDraw(CCamera *camera) {}
    virtual void OnCollision(CObject *collisionObject) {}

    virtual void OnPrepare()
    {
        ProcessCollisions(FindRoot());
    }

public:
    CVector position;
    CVector velocity;
    CVector acceleration;
    scalar_t size;

    bool isDead;

    CObject() {isDead = false;}
    ~CObject() {}
...
...
...
}

//---------------------------------------class CEnemy 
class CEnemy : public CObject
{
public:
    int hitPoints;
protected:

    float distFromPlayer;
    float runSpeed;
    AIState_t aiState;

    virtual void OnProcessAI() {}
    void OnCollision(CObject *collisionObject)
    {
          // if this enemy collides with another enemy
          if (typeid(*collisionObject) == typeid(CEnemy))
          {
               modelState = MODEL_IDLE;
               velocity = CVector(0.0, 0.0, 0.0);
          }
          // if this enemy collides with the terrain (always)
          else if (typeid(*collisionObject) == typeid(CTerrain))
          {
               position.y = ((CTerrain*)collisionObject)->GetHeight(position.x, position.z) + size;
          }
          else
          {
          }
     }

public:
    CPlayer *player;
...
...

//----------------------------------class COgro-------------------------
class COgroEnemy : public CEnemy
{
protected:
    void OnProcessAI();
    void OnCollision(CObject *collisionObject);
    void OnPrepare();

public:
    COgroEnemy() { Load(); }
    COgroEnemy(float x, float z) { position.x = x; position.z = z; Load(); }
    ~COgroEnemy() {}

    void Load();
};

You'll need to cast the pointer to a pointer type CEnemy* (or a subclass), or the dereferenced pointer to a reference type CEnemy& . For maximum safety, I'd suggest dynamic_cast , rather than an evil C-style cast; although that's slightly paranoid since you're checking the type before casting.

// no checks, undefined behaviour if type is wrong
((CEnemy*)collisionObject)->hitPoints -= 10;
static_cast<CEnemy*>(collisionObject)->hitPoints -= 10;

// throws if type is wrong
dynamic_cast<CEnemy&>(*collisionObject).hitPoints -= 10;

// does nothing if type is wrong
if (CEnemy* enemy = dynamic_cast<CEnemy*>(collisionObject)) {
    enemy->hitPoints -= 10;
}

You might combine that with the type check, rather than using typeid :

if (COgro * ogro = dynamic_cast<COgro*>(collisionObject)) {
    ogro->hitPoints -= 10;
}

Note that this isn't exactly the same as your test: it will pass if the object is a subtype of COgro , while your test checks for an exact match.

You code is not compiling because you are trying to access a class's protected data member from an external source.

The collisionObject parameter is an instance of CObject , which does not have a hitPoints data member.

Also, when you pass around pointers to base classes to functions, the functions should assume that they can only access the interface or features of the base class.

You should write another overloaded method:

void CRocket::OnCollision(CEnemy& enemy);

Or move the hitPoints data member to the CObject class.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM