C++ class dependencies - c++

I'm having some problems with my class because they both depends on each other, to one can't be declared without the other one being declared.
class block: GtkEventBox {
public:
block(board board,guint x,guint y): image("block.png") {
this.board = board;
this.x = x;
this.y = y;
board.attach(this,x,y,x+1,y+1);
}
void move(guint x,guint y) {
board.remove(this);
this.x = x;
this.y = y;
board.attach(this,x,y,x+1,y+1);
}
private:
guint x, y;
board board;
GtkImage image;
};
class board: Gtk::Table {
public:
board(): Gtk::Table(25,20) {
blocks_c = 0;
}
void addBlock(guint x,guint y) {
blocks_a[blocks_c++] = new block(this,x,y);
}
private:
block* blocks_a[24];
int blocks_c;
};
As you can see the "block" class needs to know what a "board" is and vice versa. Thanks in advance!

Define "board" before "block" and forward declare the "block" class. Also, move the implementation of the board functions out of the class definition.
// forward declare block class
class block;
// declare board class
class board: Gtk::Table {
public:
board();
void addBlock(guint x,guint y);
private:
block* blocks_a[24];
int blocks_c;
};
// declare block class
class block: GtkEventBox {
public:
block(board board,guint x,guint y);
void move(guint x,guint y);
private:
guint x, y;
board board;
GtkImage image;
};
// define member functions (implementation) here...

Forward-declare your block class before board with this line:
class block;
Place the code of the function bodies AFTER declarations of both classes. Forward-declaring your class doesn't make all its functions available, it just allows the compiler to know that such class exists. It just allows to use, for instance, pointers to such a class (because the size of pointer type doesn't depend on the layout of the class).

This can easily be resoved with a forward declaration. Since board doesn't need to know anything much about the block class, only that it uses a pointer to it, declare it first. but before that include a forward declaration for block. It looks like this:
class block; // <- Forward declaration!
class board: Gtk::Table {
public:
board(): Gtk::Table(25,20) {
blocks_c = 0;
}
void addBlock(guint x,guint y) {
blocks_a[blocks_c++] = new block(this,x,y);
}
private:
block* blocks_a[24];
int blocks_c;
}; class block: GtkEventBox {
public:
block(board board,guint x,guint y): image("block.png") {
this.board = board;
this.x = x;
this.y = y;
board.attach(this,x,y,x+1,y+1);
}
void move(guint x,guint y) {
board.remove(this);
this.x = x;
this.y = y;
board.attach(this,x,y,x+1,y+1);
}
private:
guint x, y;
board board;
GtkImage image;
};

This is usually a design problem. I suggest you to pick the smaller class (in your case I'd suggest the block class) and code some events on it that the board class would sign. Then instead of calling the board class method, shoot the event and let the board class call it itself.

Related

I'm having trouble figuring out how to access a variable outside of a nested class

The nested class can't access non-static elements that are outside of the class
Something is wrong with nested classes, as you can see by the code i've provided, 2 classes have been declared, the nested class Entity is inside the private field of the class Game, for some reason the nested class doesn't allow me to access the variable outside of it map_info.
I've only found 1 solution and it involves creating an instance of the Game class inside the Entity class.
class Game
{
private:
std::string map_info;
class entity
{
protected:
double x, y, z;
public:
};
class player : public entity
{
private: std::string name;
player(std::string _name) : name(_name) {};
void check()
{
/*
this is the portion of the code that i'm having problem with
the error: "a nonstatic member reference must be relative to a specific object"
*/
if (map_info != 'none')
{
// do stuff
}
}
};
public:
std::string Getmap() { return map_info; }
Game() //constructor
{
// does stuff
}
};
Here's something i tried doing
Declaring map_info as a static type (doesn't solve the problem)
Declaring an instance of the game class inside of the nested class
I've searched here for the same problem but the results don't fit my original code, however there might be a slight chance that i've missed something and if so please send the link.
It's my first question in this website so give as much feedback as you can, even the slightest is appreciated! Thanks!
That doesn't works as you want. Nested class is just class-member of your Game class, which can be accessed as Game::NestedName if it's public, and cannot be accessed not in class if it's private. For example
#include <vector>
class Game
{
public:
Game(){};
void spawnNewPrivateEntity(double x, double y, double z)
{
private_entities.push_back(PrivateEntity{x, y, z}); //access to private member PrivateEntity is ok
}
struct PublicEntity { double x, y, z; }; //public nested struct, can be accessed from everywhere
void spawnNewPublicEntity(PublicEntity entity)
{
public_entities.push_back(entity);
}
private:
struct PrivateEntity { double x, y, z; }; //private nested struct, can be used only inside this class or friend members
std::vector<PrivateEntity> private_entities = {};
std::vector<PublicEntity> public_entities = {};
}
int main()
{
auto en = Game::PublicEntity{0.0, 9.0, 1.9}; //works
auto en2 = Game::PrivateEntity{0.0, 0.0, 0.0}; //doesn't work: this struct is private member of Game class
}
You can make something like this:
class Game
{
public:
Game(std::string map_info): map_info(map_info)
{};
std::string getMapInfo() { return map_info; }
private:
std::string map_info;
};
class Entity
{
public:
Entity(Game *game): game(game)
{};
void check()
{
if (game->getMapInfo() != "none") { /*some code*/ }
};
private:
Game *game;
}

C++ code that cannot access private members of a class using derived class

I've currently got code below in which i am trying to initialize the data members x, y and z to 0 when an object of type Solid is being instantiated. The lines 25, 26 and 27 contain errors, how would I rewrite these lines to access the x and y members and set them to 0?
edit 1: I've written out my code below.
edit 2: To clear things up, the only lines of code that can be altered are the lines that contain errors. The derived class should be rewritten to access the private data members.
class Shape
{
private:
int x, y;
protected:
string _type;
public:
Shape() { x = y = 0; }
Shape(int a, int b) { x = a; y = b; }
string type() { return _type; }
void stype(string val) { _type + val; }
int getx() { return x; }
int gety() { return y; }
};
class Solid : public Shape
{
int z;
public:
Solid() { x = y = z = 0; } // errors
Solid(int a, int b, int c) { x = a; y = b; z = c; } //
int Volume() { return x * y * z; } //
};
int main()
{
Solid ob1;
return 0;
}
You can't access private members of a base class, and the point of this exercise is that you don't need to - not that you should come up with a way of doing it.
Your default constructor should only set its own member - Shapes default constructor takes care of its own members:
Solid() { z = 0; }
or (the preferred method, which actually is initialisation and not an assignment)
Solid() :z(0) {}
The other constructor should initialise the base, and then z:
Solid(int a, int b, int c) : Shape(a,b), z(c){}
and Volume should use the provided accessors:
int Volume() { return getx() * gety() * z; }
Inherited class can not access to parent's private attributes. It can access his protected attributes, so you can move your variables to protected. Another option is to use setter function (like getX) and use them.
edit: change only for the relevant errors lines:
Solid():Shape(0,0) { this->z = 0; }
Solid(int a, int b, int c):Shape(a,b) { this->z = c; }
int Volume() { return this->getx() * this->get.y * this->z; }
when you create Solid object, you can also call for the c'tor of Shape with the values you want. That is the right way to initialize values of x, y when creating new inherited objects. For the third line calculation you should use getx() and gety() functions.
As said before, the key is to understand that x and y are not directly accessible for Solid object
You can't, directly, inherit the private members of the parent class. You could use its constructor in your derived class(child class) constructor though-its cool, but I don't use that way. Some information about the access specifiers(the type of inheritance you declare):
Public: Your derived class inherits the protected members of your parent class as protected and the public as public.
Protected: Your derived class inherits the protected members of your parent class as protected and the public as protected.
Private: Your derived class inherits the protected members of your parent class as private and the public as private.
Notice again that the private members of your parent class are not inherited. This should do the trick:
Change:
private:
int x, y;
Into:
protected:
int x, y;
Using the parent class constructor should look like:
class Solid : public Shape
{
private://doesn't matter, just for the aesthetics
int x;
int y;
int z;
public:
Solid() {
Shape();
z = 0; } // errors
And the direct way is(your code with added x,y as properties of the class):
class Solid : public Shape
{
private://doesn't matter, just for the aesthetics
int x;
int y;
int z;
public:
Solid() {x=y=z = 0; } // errors
Private data members are never inherited in any type of inheritance. Hence the name private, but interestingly you can use friend class concept here and even private data members are inherited now,
please try to run the following code:
#include <bits/stdc++.h>
using namespace std;
class Shape
{
private:
int x, y;
protected:
string _type;
public:
Shape() { x = y = 0; }
Shape(int a, int b) { x = a; y = b; }
string type() { return _type; }
void stype(string val) { _type + val; }
int getx() { return x; }
int gety() { return y; }
friend class Solid;
};
class Solid : public Shape
{
int z;
public:
Solid() { x = y = z = 0; } // errors
Solid(int a, int b, int c) { x = a; y = b; z = c; } //
int Volume() { return x * y * z; } //
};
int main()
{
Solid ob1;
return 0;
}
Now you can access x, y in inherited class also, since you declared class solid as friend of shape class.
Hope this answers your question.

Overwriting properties of abstract class

I am defining a class GameState and a class MainMenuGameState. The former is meant to be an abstract class and the latter is inheriting it. But somehow, I am not able to overwrite its properties.
GameState.h
#ifndef _GAME_STATE_H_
#define _GAME_STATE_H_
#include <SDL2/SDL.h>
class GameState {
public:
virtual void loop(Uint32 deltaTime) = 0;
virtual void render() = 0;
virtual void event(SDL_Event * event) = 0;
bool stopRenderPropagation = false;
bool stopLoopPropagation = false;
};
#endif
MainMenuGameState.h
#ifndef _MAIN_MENU_GAME_STATE_H_
#define _MAIN_MENU_GAME_STATE_H_
#include "../Game.h"
class MainMenuGameState : public GameState {
public:
MainMenuGameState(Game * pGame);
void loop(Uint32 deltaTime);
void render();
void event(SDL_Event * event);
bool stopRenderPropagation = true;
bool stopLoopPropagation = true;
private:
Game * game;
int xOffset = 0;
int yOffset = 0;
};
#endif
So after instanciating a MainMenuGameState object, I expected stopRenderPropagation and stopLoopPropagation to be true, but they are false.
I also had no luck overwriting them inside the constructor for some reason.
MainMenuGameState::MainMenuGameState(Game * pGame) {
game = pGame;
xOffset = rand() % 20;
yOffset = rand() % 20;
stopRenderPropagation = true;
stopLoopPropagation = true;
}
After that, they are still true. I don't know weather this is a problem with my constructor or if I misunderstood polymorphism in c++.
The instances of MainMenuGameState get stored in a vector<GameState *>, could this be the problem? I am accessing the properties like this:
if(gameStates.begin() != gameStates.end()) {
std::vector<GameState *>::iterator it = gameStates.end();
do {
--it;
} while(it != gameStates.begin() && (*it)->stopLoopPropagation == false);
while(it != gameStates.end()) {
(*it)->loop(deltaTime);
++it;
}
}
Thank you for your help!
Your derived class is declaring another couple of members with the same name of the members in the base class, thus "hiding" the base ones.
You should accept the initial values for those members in the constructor, or if they are fixed properties of the class that never change you should make them member functions instead like in
class GameState {
public:
...
virtual bool stopRenderPropagation() { return false; }
virtual bool stopLoopPropagation() { return false; }
};
class MainMenuGameState : public GameState {
public:
...
bool stopRenderPropagation() { return true; }
bool stopLoopPropagation() { return true; }
...
};
Inheriting data members (your booleans) does not work in the same way as inheriting and overloading methods. Try putting the bools as protected inherited data members instead (uninitialized), and initialize them in the respective subclass constructors instead.
class MainMenuGameState : public GameState {
public:
MainMenuGameState(Game * pGame);
void loop(Uint32 deltaTime);
void render();
void event(SDL_Event * event);
protected:
bool stopRenderPropagation;
bool stopLoopPropagation;
private:
Game * game;
int xOffset = 0;
int yOffset = 0;
};
You declare new variables in your derived class, which is leading to these problems. Variables that are not private are inherited:
struct A { int x };
struct B : A {}; // has B::x by inheritance
You can just set them in your constructor without redeclaration:
struct A { int x; };
struct B : A { B() : x(1) {} };
Notice that it is usually considered bad practice to declare public variables, it is more common to implement getters and setters instead:
struct A
{
int x() const { return x_; }
int & x() { return x_; }
private:
int x_;
};

C++, get pointer 0xcdcdcdcd creating a public class from another class

I get this:
This is a sample code of the two classes:
main.h
class CControl
{
protected:
int m_X;
int m_Y;
public:
void SetX( int X ) { m_X = X; }
void SetY( int Y ) { m_Y = Y; }
int GetX() { return m_X; }
int GetY() { return m_Y; }
CControl *m_ChildControls;
CControl *m_NextSibling;
CControl *m_PreviousSibling;
CControl *m_Parent;
CControl *m_FocusControl;
};
class CButton : public CControl
{
protected:
bool m_Type;
bool m_Selected;
bool m_Focused;
public:
CButton( bool Type );
~CButton();
};
CButton::CButton( bool Type )
{
}
This is just the declarations of the two classes (they're not complete, but the problem comes in also in the full coded version).
main.cpp
#include <windows.h>
#include "main.h"
int main()
{
CButton *g_Button;
g_Button = new CButton( 1 );
return 0;
}
This is just the application main func where I declare g_Button as a new CButton object for making a debugging analysis.
Are you referring to the CControl * members? Since you didn't initialize them in the constructor it's normal that they are at some "random" value; in particular, the value you see is the pattern used in debug builds in VC++ to mark uninitialized memory.
The same holds also for the other fields of your class (-842150451 is the 32-bit signed integer interpretation of 0xcdcdcdcd).
The pointers could be anything, because they're not initialized.
The compiler generated default constructor for CControl doesn't initialize POD members. You'd need to write your own:
CControl() : m_ChildControls(NULL), m_NextSibling(NULL), m_PreviousSibling(NULL)
m_Parent(NULL), m_FocusControl(NULL)
{
}
You need to initialize the data members of the class in the constructor.
CButton::CButton( bool Type )
{
m_Type = Type;
m_X = m_Y = 0;
m_ChildControls = NULL;
// ...
}

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.
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.
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).
I'd bet that since Character is a protected base class, its restricting the access to Sprite.