Error C2227,C2065, Class within a Class - c++

I'm trying to structure my code like this main <- game <- player.
IF I write in main:
player* P;
P = new player;
P->move();
Everything works but when trying to move this code in to the game component I run in to problems.
Here is the parts of game.cpp I need help with.
#include "game.h"
#include <string>
using namespace std;
game::game(){
player* P;
P = new player;
};
void game::playerStuff(){
P->move(); //c2227+C2065
};
Here is a part of game.h
#include "player.h"
class game {
public:
game();
void playerStuff();

The issue is rather simple. Your pointer to the player (P) is a local variable only visible/existing within your constructor. Add it as a class member instead to use it everywhere in your game class:
class game
{
private:
player *P;
public:
game();
// other stuff ...
}

P needs to be a member of the game class.
Currently, in your constructor here:
game::game(){
player* P;
P = new player;
};
P is local to the ctor and disappears as soon as this function ends.
Solution
Make P a member of game:
class game {
private:
player * P;
public:
game();
~game(); // NOTE: I have added a destructor
void playerStuff();
}
And change the contructor:
game::game(){
P = new player;
};
Remembering of course, to delete it in the destructor:
game::~Game(){
delete P;
};
Of course, because you include <player.h>, you don't need to allocate this object on the heap at all, and can use the stack instead, thereby negating the need to delete P in the destructor.
EDIT: Here is an example showing using the stack, rather than allocating on the heap:
#include "player.h"
class game
{
private:
player P; // Note, we're not declaring a pointer.. we have a complete type here.
public:
game();
~game();
void playerStuff();
}; // eo class game
game.cpp
game::game()
{
// No need to allocate, it's already allocating on the stack
}; // eo ctor
game::~game()
{
// No need to delete, P will be deallocated along with this game class.
}; // eo dtor
void game::playerStuff()
{
P.move(); // note we're not using -> (pointer to member) here
} // eo playerStuff

Move #include "player.h" to game.cpp if you need only pointers or references on game.h. If you need to reference Player on game.h to declare a pointer, you can use a forward declaration, like:
class Player;
class game
{
Player *myPlayer;
};

Related

C++ state machine, inherited class with member values with incorrect syntax

I don't know if my question title makes sense, so apologies in advance for that. so... I'm trying to implement a state machine for a little game I'm trying to make using C++ and SFML.
I have a GameLoopObject abstract class which needs a renderwindow argument and has these virtual methods: update, draw, handleinput and reset.
Then I have a GameState abstract class which inherits from GameLoopObject, but doesnt add anything new yet so its basically the same as GameLoopObject, for now.
Last, I have a GameStateManager class which also inherits from GameLoopObject and should handle my gamestates.
Now my problem is that I want to use a GameState currentState and a nextState member variable in my GameStateManager, but I can't seem to find the correct way/syntax to declare these and use them afterwards. I'd prefer leaving them empty (if that's possible in C++), as GameState objects are being stored inside of them immediately after making a GameStateManager object.
Basically, what I'm trying to do is something along the lines of this:
GameStateManager(sf::RenderWindow & w) :
GameLoopObject(w),
currentState(new GameState(w)),
nextState(new GameState(w));
Which gives me a "no default constructor exists for class "GameLoopObject" "
This is the rest of my code:
/*
* GameStateManager.hpp
*/
#ifndef GameStateManager_HPP
#define GameStateManager_HPP
#include "stdafx.h"
#include "GameLoopObject.hpp"
#include "GameState.hpp"
#include<string>
#include<map>
class GameStateManager : GameLoopObject {
private:
GameState currentState;
GameState nextState;
public:
std::map<std::string, GameState> gameStates{}; // list where all known gamestates are stored.
// methods
GameStateManager(sf::RenderWindow & w);
void AddGameState(std::string name, GameState * state);
void SetNext(std::string name);
void SwitchState();
void HandleInput();
void Update();
void Draw();
void Reset();
};
#endif //GameStateManager_HPP
/*
* GameStateManager.cpp
*/
#include "stdafx.h"
#include "GameStateManager.hpp"
GameStateManager::GameStateManager(sf::RenderWindow & w)
// : GameLoopObject(w)
{
GameState currentState(w);
GameState nextState(w);
}
void GameStateManager::AddGameState(std::string name, GameState * state)
{
gameStates.insert(std::make_pair(name, * state));
}
void GameStateManager::SetNext(std::string name)
{
//check if user wants to exit (close window with X)
if (gameStates.count(name))
{
nextState = gameStates[name];
}
}
void GameStateManager::SwitchState()
{
if (currentState != nextState)
{
currentState = nextState;
}
}
void GameStateManager::HandleInput()
{
// if(currentState != null)
currentState.HandleInput();
}
void GameStateManager::Update()
{
// if(currentState != null)
currentState.Update();
}
void GameStateManager::Draw()
{
// if(currentState != null)
currentState.Draw();
}
void GameStateManager::Reset()
{
// if(currentState != null)
currentState.Reset();
}
I see you have two issues here, both stemming from the fact that you can't declare an instance of an abstract class. The members of the class should be GameState pointers. You also face the same issue when you call new GameState, there is no constructor available here as GameState is abstract.
I'm not sure whether your GameStateManager is the owner of the current and next state. In the case that it is, you should change the type of your members to std::unique_ptr<GameState>, otherwise just use a GameState*.
Your constructor doesn't need to create a new GameState object to initialise these members if they don't own the states, in this case you would pass a pointer to an existing GameState. However if they do, you must call new ConcreteGameState where ConcreteGameState is some derived class of GameState that is not abstract.
EDIT:
Looking at your member functions, you almost definitely want to a raw pointer.
EDIT 2:
Noticed you are currently privately inheriting from GameLoopObject, you should change that to public by adding the keyword:
class GameStateManager: public GameLoopObject

Double Delete using Shared Pointers, even though there is still a shared_ptr to the object, its destructor is being called

I apologize if this is a lot of code to read, if I can simplify with explanations please let me know, also if you'd like to comment on my design/practices feel free.
So my Player is being deleted twice, I'm not sure why. If you look at the call stack, you'll see that GameEventManager is actually calling the Player destructor before the GameState destructor, even though GameState is the one with the pointer to Player. I'm thinking maybe this is because it's also destroying the vector first, so it finds Player in the vector and tries to destroy it. I don't know why it would try to destroy the Player though, since there is still a reference to Player that the GameState object knows about. The shared pointer functionality should prevent the Player from being destroyed.
Maybe I am going about it the wrong way, if so could someone point me in the correct direction for best practices here? Thanks
Call stack:
GameState.h
#ifndef _level
#define _level
#include <vector>
#include "Player.h"
#include <memory>
using namespace std;
class GameState // A representation of the Level/Game/Scene
{
public:
GameState();
virtual ~GameState() {}
//Keep track of the game's state
//Maybe get rid of the Level class, and make this a class, and move the Level functionality here?
static void EndGame(const bool & b) { mbEndGame = b; }
static const bool & EndGame() { return mbEndGame; }
private:
void SetPlayer(shared_ptr<Player> sptrPlayer) { msptrPlayer = sptrPlayer; }
static bool mbEndGame;
shared_ptr<Player> msptrPlayer;
vector<shared_ptr<Player>> msptrMob; // Representation of all the NPCs in the game. Eventually make a Mob class but for now just use Player
// shared_ptr<LevelMap> mMap // Representation of what the game looks like visually
// Renderer // Should the level have the renderer to create the graphics? Or should this be handled by another "GUI Layer" and interact with this layer as little as possible ?
};
#endif
GameState.cpp
#include "stdafx.h"
#include "GameState.h"
bool GameState::mbEndGame(false);
GameState::GameState() : msptrPlayer(NULL)
{
shared_ptr<Player> sptrPlayer(new Player);
SetPlayer(sptrPlayer);
}
GameObject.h
#ifndef _game_object
#define _game_object
#include <memory>
// Game Object Classes inherit this so they are registered with GameEventManager.
using namespace std;
class GameObject{
public:
GameObject();
virtual ~GameObject() {}
virtual void Update() = 0;
virtual void Start() = 0;
};
#endif
GameObject.cpp
#include "stdafx.h"
#include "GameObject.h"
#include "GameEventManager.h"
GameObject::GameObject()
{
shared_ptr<GameObject> ptr(this);
GameEventManager::GetGameEventManager()->RegisterGameObject(ptr);
}
Player.h
#ifndef _player
#define _player
#include "GameObject.h"
//A representation of the Player. Used by Level.
class Player : public GameObject
{
public:
Player();
virtual ~Player() {}
private:
virtual void Update();
virtual void Start();
int miMaxHealth;
};
#endif
Player.cpp
#include "stdafx.h"
#include "Player.h"
#include "GameState.h"
Player::Player() : miMaxHealth(100) {};
void
Player::Start()
{
}
void
Player::Update() // reimplement GameObject::Update(), which is called by the GameEventManager
{
--miMaxHealth;
if (miMaxHealth <= 0)
{
GameState::EndGame(true);
}
}
GameEventManager.h
#ifndef _game_event_manager
#define _game_event_manager
#include "stdafx.h"
#include <memory>
#include <vector>
#include "GameObject.h"
#include "GameState.h"
using namespace std;
class GameEventManager{
//Object which inherit from GameObject are automatically registered with GameEventManager when they are constructed.
// GameEventManager creates the level object to represent the game, and then runs Start() on all registered GameObjects
// and then continually runs Update() on all registered game objects until the GameState is set to EndGame.
public:
virtual ~GameEventManager(){} // This gets called at the end of the program (I guess whne static variables are destroyed), and crashes during vector<shared pointer <GameObject>> destruction, probably because
// Player already destroyed it. So... not sure what to do. If I make it non-static
void StartGameEvents();
const static shared_ptr<GameEventManager>& GetGameEventManager();
const shared_ptr<GameState>& GetLevel();
void RegisterGameObject(shared_ptr<GameObject> sptrGameObject);
const shared_ptr<vector<shared_ptr<GameObject>>>& GetRegisteredGameVector() const { return mvecRegisteredGameVector; }
private:
GameEventManager(); //singleton
void AddGameObject(shared_ptr<GameObject>);
shared_ptr<GameState> mLevel;
shared_ptr<vector<shared_ptr<GameObject>>> mvecRegisteredGameVector; //Reference because shared pointer will double delete otherwise. ~Level() still deletes it but this way I guess it doesn't try to delete again? but...
//Now I'm trying it as a shared_ptr, but it's not working. ~Level() still deletes it even though there is a shared pointer to a vector pointing to the Player. Why is ~Level() doing this?
static shared_ptr<GameEventManager> msptrGameEventManager;
};
#endif
GameEventManager.cpp
#include "stdafx.h"
#include "GameEventManager.h"
#include "GameState.h"
shared_ptr<GameEventManager> GameEventManager::msptrGameEventManager(new GameEventManager);
void
GameEventManager::StartGameEvents()
{
//run once
int size = GetRegisteredGameVector()->size();
vector<shared_ptr<GameObject>> & vecsptrRegisteredGameVector = (*GetRegisteredGameVector());
for (int i = 0; i < GetRegisteredGameVector()->size(); ++i)
{
vecsptrRegisteredGameVector[i]->Start(); //nothing for now
}
//keep running
while (GetLevel()->EndGame() != true)
{
for (int i = 0; i < GetRegisteredGameVector()->size(); i++)
{
(*GetRegisteredGameVector())[i]->Update(); //Player's life goes from 100 to zero, see Player::Update
}
}
return;
// GameState destructor is called and destroys player for some reason, even though it's still being referenced by the GameEventManager's vector.
}
GameEventManager::GameEventManager() : mvecRegisteredGameVector(new vector<shared_ptr<GameObject>>) , mLevel(NULL) //Instantiating the level before the GameEventManager is fully instantiated causes an infinite recursion.
{
return;
}
const shared_ptr<GameEventManager>&
GameEventManager::GetGameEventManager()
{
if (!msptrGameEventManager)
{
msptrGameEventManager.reset(new GameEventManager);
}
return msptrGameEventManager;
}
const shared_ptr<GameState>&
GameEventManager::GetLevel()
{
if (!mLevel)
{
mLevel.reset(new GameState);
}
return mLevel;
}
void
GameEventManager::RegisterGameObject(shared_ptr<GameObject> sptrGameObject)
{
GetGameEventManager()->AddGameObject(sptrGameObject);
}
void
GameEventManager::AddGameObject(shared_ptr<GameObject> sptrGameObject)
{
GetRegisteredGameVector()->push_back(sptrGameObject);
}
GameObject::GameObject()
{
shared_ptr<GameObject> ptr(this);
GameEventManager::GetGameEventManager()->RegisterGameObject(ptr);
}
The ptr in this function does not share ownership with any other shared_ptr constructed independently, like the one declared at shared_ptr<Player> sptrPlayer(new Player);. Creating two shared_ptr from raw pointers, rather than copying the first one, generally leads to a double delete.
Instead, you could do something like this:
class GameObject :
public std::enable_shared_from_this<GameObject>
{
protected:
GameObject(); // creates the original shared_ptr
virtual ~GameObject();
};
class Player : public GameObject
{
public:
static std::shared_ptr<Player> create();
private:
Player() : GameObject() {}
virtual ~Player() {}
};
std::shared_ptr<Player> Player::create() {
return dynamic_pointer_cast<Player>((new Player)->shared_from_this());
}
A player is inherited from a GameObject (class Player : public GameObject). During the gamestate construction, it is set as the player.
GameState::GameState() : msptrPlayer(NULL)
{
shared_ptr<Player> sptrPlayer(new Player);
SetPlayer(sptrPlayer);
}
You add the object to a std::shared_ptr object. But, the parent class GameObject also creates a std::shared_ptr object, and adds the same pointer:
GameObject::GameObject()
{
shared_ptr<GameObject> ptr(this);
GameEventManager::GetGameEventManager()->RegisterGameObject(ptr);
}
The same pointer is added to two separate std::shared_ptr objects. So both shared pointer objects will delete the object, causing your problem.

Instantiate an object of one class in the constructor of another class C++?

I'm writting a basic game in C++ which features 3 classes: Game class, Character class and Item class.
The Game class will have all the logic of the game, so that the main function will just simply create the Game object, call its logic function and the game will do everything else. There can be more than 1 player.
The Character class has a vector of pointers that can hold one or more Items. A character can have one or more items
The Item class has all the attributes and functionality of the item.
I'm stuck at designing the structure of the game. Someone suggested me to structure my game in a way that when the Game object is created, it also creates an Character object, and that Character object will then create a vector of pointers to hold Item, and the Item object. So it likes when I call the constructor of the Game class, it will call the constructor of the Character class, and the constructor of the Character class will automatically call the constructor of the Item class.
It makes sense, but I couldn't figure out how to properly implement it.
This is what I've got
This is what I have so far:
Game.cpp
Game::Game()
{
vector<Character*> characterVector; //to hold Characters
}
Game::startLogic()
{
string name;
Character character = new Character(name);
}
Character.cpp
Character::Character(string name)
{
m_name = name;
vector<Item*> itemVector;
}
Item.cpp
Item::Item()
{ //initialise all the attributes of an item
}
main.cpp
void main()
{
Game g;
g.startLogic();
}
So I could create a character when the game runs (I still have to push that character into the characterVector later though), but I'm not quite sure on how to create items for that character. I means where should I put that instantiate code? In the startLogic function, in the constructor of Game, or in the constructor of Character?
Your vectors are in the wrong places. You need to move them into the class declarations as class members, not as local variables inside the constructors. The constructors can fill the vectors (but really, do characters know what items they are "born" with, and do games know what characters are alive as soon as the game start?), but should not declare them.
Try this instead:
Game.h
#include <vector>
class Character;
class Game
{
public:
std::vector<Character*> characters;
Game();
~Game();
void startLogic();
};
Game.cpp
#include "Game.h"
#include "Character.h"
#include <memory>
Game::Game()
{
}
Game::~Game()
{
for (std::vector<Character*>::iterator i = characters.begin();
i != characters.end();
++i)
{
delete *i;
}
}
Game::startLogic()
{
...
// using auto_ptr as a safety catch in case of memory errors...
std::auto_ptr<Character> c(new Character("Joe Smoe"));
std::auto_ptr<Item> i(new Item);
c->items.push_back(i.get());
i.release();
characters.push_back(c.get());
c.release();
...
}
Character.h
#include <string>
#include <vector>
class Item;
class Character
{
public:
std::string name;
std::vector<Item*> items;
Character(std::string aName);
~Character();
};
Character.cpp
#include "Character.h"
#include "Item.h"
Character::Character(std::string aName)
: name(aName)
{
}
Character::~Character()
{
for (std::vector<Item*>::iterator i = items.begin();
i != items.end();
++i)
{
delete *i;
}
}
Item.h
class Item
{
public:
Item();
};
Item.cpp
#include "Item.h"
Item::Item()
{ //initialise all the attributes of an item
}
main.cpp
int main()
{
Game g;
g.startLogic();
return 0;
}

C++ Static List of object pointers, and memory leak

I am trying to have a class that contains a static list of pointers to instances of the class, but I am getting a memory leak. I was wondering if anyone could point out what is wrong with the following code. I have a feeling its either to do with the destructor, or the void creature::kill() function. I note that I am using allegro but have not included some functions which are not doing anything special.
Firstly the class header:
class creature{
private:
//some data for other functions
public:
static std::list<creature*> mycreatures;
creature();
~creature();
void kill();
};
the class .cpp file
#include "creature.h"
std::list<creature*>creature::mycreatures;
creature::creature(){
mycreatures.push_back(this);
}
creature::~creature(){
std::list<creature*>::iterator p =
find(mycreatures.begin(),mycreatures.end(),this);
if(p != mycreatures.end()){
mycreatures.erase(p);
}
}
void creature::kill(){
if(mycreatures.size()>0){
std::list<creature*>::iterator it = --mycreatures.end ( );
delete (*it);
}
}
and the main
#include "creature.h"
void main (void){
creature a;
while(!key[KEY_ESC]){
std::list<creature*>::iterator it;
for(it=a.mycreatures.begin(); it!=a.mycreatures.end(); it++)
{
(*it)->//some other non included functions
}
if(key[KEY_N]){
new creature();
}
if(key[KEY_K]){
a.kill();
}
}
allegro_exit();
}
END_OF_MAIN();
creature a;
Ack! You have code that calls delete on a creature without calling new on that creature. For this to work, you must always create creatures using new and never create them on the stack! What happens if this creature is killed while it's still in scope? Boom.

C++ Referencing an objects current state within another object

I've searched high and low for an answer to this question and have attempted many solutions including forward declaration, pointers, and references. I'm sure I'm just using incorrect syntax somewhere. After many wasted hours, I've decided to turn to stack overflow.
I am attempting to code one of my first CPP applications as a learning experience. Right now I have a Player and a Ball object. My Ball object must be able to access some of the member variables and methods in my player object. I have been unable to figure out how to do this. Below is an extremely simplified version of my code. I've commented the code that is particularly important.
PlayState.hpp
#ifndef PLAYSTATE_HPP
#define PLAYSTATE_HPP
#include "Player.hpp"
#include "Ball.hpp"
class Player;
class Ball;
class PlayState
{
public:
PlayState();
Player player;
Ball ball;
};
#endif
PlayState.cpp
#include "PlayState.hpp"
PlayState::PlayState() {
}
void PlayState::update() {
if (sf::Keyboard::isKeyPressed(sf::Keyboard::W))
{
ball.checkCollision();
player.move(1);
}
ball.update();
}
void PlayState::draw()
{
m_game.screen.clear();
m_game.screen.draw( player.getSprite() );
m_game.screen.draw( ball.getSprite() );
m_game.screen.display();
}
Player.hpp
#ifndef PLAYER_HPP
#define PLAYER_HPP
class Player
{
public:
Player();
~Player();
void create();
void setRotation(float);
void setPosition(float, float);
};
#endif
Player.cpp shouldn't really be all that important to see.
Ball.hpp
#ifndef BALL_HPP
#define BALL_HPP
class Player; // I don't think forward declaration is what I need???
class Ball
{
public:
bool picked_up;
bool throwing;
Player *player; // this isn't working
Ball();
~Ball();
bool checkCollision();
};
#endif
Ball.cpp
#include "Ball.hpp"
Ball::Ball() {
Ball::picked_up = false;
Ball::throwing = false;
}
Ball::~Ball() {
}
bool Ball::checkCollision()
{
float ball_position_x = Ball::getPosition().x;
float ball_position_y = Ball::getPosition().y;
// I need to access the player object here.
float x_distance = abs(player.getPosition().x - ball_position_x);
float y_distance = abs(player.getPosition().y - ball_position_y);
bool is_colliding = (x_distance * 2 < (player.IMG_WIDTH + Ball::width)) && (y_distance * 2 < (player.IMG_HEIGHT + Ball::height));
return is_colliding;
}
When you say player, do you mean the exact same player that is in the same playstate object as the current ball object? If so you want to first set up that link, it cannot be done automatically.
PlayState::PlayState() :ball(&player){ //pass pointer to ball of its player?
}
class Ball
...
Ball(Player *myPlayer);
...
}
Ball::Ball(Player *myPlayer):player(myPlayer) {
...
// I need to access the player object here.
float x_distance = abs(player->getPosition().x - ball_position_x);
You also need to use a pointer to use the player since it is a pointer to a player object.
You do need the forward declaration to Player above the Ball class. The one above Playstate is unnecessary.
Also your player doesnt seem to have a GetPosition function, I am assuming it is a public member function you forgot to include above.