Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inaccessible base class

I'm writing a simple game in SDL. I have a class heirarchy that I am constructing for any sprite I use in the game. The base class is Sprite, which contains data abstractions for the collision box and the spritesheet. Directly below that are two abstract classes, Character and MapObject.

I am currently implementing the Player class which is derived from Character (Enemy and NPC will also be derived from the abstract Character class).

Anyway, hopefully that makes sense. My problem is this:

When I try and use the player class in the engine, I cannot access any of the Sprite functions.

I get the following error:

'Sprite' is not an accessible base of 'Player'

Here are the header files:

Sprite.h:

class Sprite{
public:
    virtual ~Sprite() = 0;  //I want this to be an abstract class and yes this is defined in the cpp

    //Initialization functions - MUST be called before anything else in the class can be used.
    void setupCollider(int xo, int yo, int ho, int wo);
    void setupSheet(SDL_Surface* dest, std::string file, int numClips, int ac, int _res, int sr);

    //SpriteSheet functions
    void setActiveClip(int a);
    int getActiveClip() const;
    void draw() const;
    int getResolution() const;
    SDL_Surface* getDest();


    //Collider functions
    void updateCollider();
    SDL_Rect box() const;
    bool collision(SDL_Rect other) const;

    //Access and Modify coordinates of the sprite
    void setLoc(int x, int y) { _x = x; _y = y; }
    int getX() const { return _x; }
    int getY() const { return _y; }

private:
    struct Collider{
        SDL_Rect  _box;
        int       x_offset,
                  y_offset;
    };

    struct SpriteSheet{
        SDL_Surface*     destination;
        SDL_Surface*    sheet;
        SDL_Rect*       clips;
        int             _numClips;
        int             active;
        int             res;
        int             sheetrows;
    };


    Collider     collisionAttributes;
    SpriteSheet  spriteSheetAttributes;
    int          _x, _y;

};

Character.h:

class Character : public Sprite{
public:
    virtual void move(Direction direction_input, const TileMap& currentlevel) = 0;
    virtual void animate() = 0;

    virtual void setAttributes( int h, int sp, int ad, int d, int m, int md, int l, std::string n){
        hearts = h; speed = sp; attackdamage = ad;
        defense = d; magicdamage = m; magicdefense = md;
        level = l; name = n;
    }

    bool isDead() const{
        return hearts == 0;
    }

    void heal(int heartsup){
        hearts += heartsup;
    }

    void dealDamage(int heartsDown){
        hearts -= heartsDown;
    }


protected:

    int hearts;
    int speed;
    int attackdamage;
    int defense;
    int magicdamage;
    int magicdefense;
    int level;
    std::string name;

};

Player.h:

//Not fully finished yet, but should work for the purposes of this question
class Player : protected Character{
public:
    ~Player(){
        if(heart) SDL_FreeSurface(heart);
    }
    static const int HEART_WIDTH;

    void move(Direction direction_input, const TileMap& currentlevel);
    void animate();

    void updateCamera(TileMap& currLevel);


 private:

    SDL_Surface* heart;

    enum ClipFace
    {
        UP1,
        UP2,
        DOWN1,
        DOWN2,
        LEFT1,
        LEFT2,
        RIGHT1,
        RIGHT2
    };

    static const std::string HEART;
    static const int HEART_RES;

};

I get the first error in my engine when I try to call the setup functions from Sprite in player, the first one being:

player.setLoc(levels[0].startX(), levels[0].startY());

Any and all help is appreciated.

[SOLVED] EDIT: An alternative solution to the comments: The character class didn't inherit anything from the Sprite class, so it didn't technically have to be derived from it. Instead of having Character inherit from Sprite, I had Player inherit from BOTH Sprite and Character and that also worked. I'm not sure what is better design though.

like image 390
Slims Avatar asked Aug 12 '12 01:08

Slims


2 Answers

I think you need to change

class Player : protected Character{

to

class Player : public Character{

That way you can access Character and Sprite's functions on a Player object from an instance of Player created anywhere in your program.

If a Player should be able to do anything a Character can do, public inheritance makes sense. There's no reason to hide something in Player that would be freely accessible in Character or Sprite objects.

like image 181
WendiKidd Avatar answered Oct 23 '22 21:10

WendiKidd


Always use public inheritance to represent an "is-a" relationship. It sounds like Player is a Character, so that inheritance should be public, not protected.

protected inheritance and private inheritance are more like "has-a" (and in most cases, a member subobject is an easier way to deal with that relationship).

like image 23
aschepler Avatar answered Oct 23 '22 21:10

aschepler