Inaccessible base class

12,065

Solution 1

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.

Solution 2

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).

Share:
12,065
Slims
Author by

Slims

Updated on June 04, 2022

Comments

  • Slims
    Slims almost 2 years

    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.

  • Slims
    Slims over 11 years
    I thought that making it protected gave it more access. So now instead of just having public it has public and protected. It seems like my understanding is lacking here. Could you elaborate more?
  • WendiKidd
    WendiKidd over 11 years
    @Slims Nope, not quite! This answer has a great explanation of private/protected/public: stackoverflow.com/a/860353/1023783 Let me know if you're still confused after reading it and I'll try to elaborate!