I'm trying to create a game in C++.
It has a "Session" class that kind of manages everything. It contains things like a GraphicsManager, a SoundManager, and the current world. It also contains a static pointer to an instance of itself. This way, I want the world to be available for the GraphicsManager so it can be rendered, for example.
Here is a simplified version of my code:
main.ccp
#pragma once
#include "Session.h"
int main() {
Session::getSession()->run(); //Starts a new session and runs it
return 0;
}
Session.h
#pragma once
#include "GraphicsManager.h"
#include "World.h"
class Session; //Forward declaration so it can have a pointer to itself
class Session {
private:
Session();
static Session* s;
World* w; //Pointer because no world is loaded at the beginning of the program
GraphicsManager gm; //Required right away
public:
~Session();
void run(); //Actually launches the game after preparation; not further declared in this example
World* getWorld(); //Returns the pointer to the current world
static Session* getSession();
}
Session.cpp
#include "Session.h"
Session::Session(): gm(GraphicsManager()) {}
Session* Session::getSession() { //Return an instance of Session. If no instance exist yet, create one.
if(s == NULL) s = new Session();
return s;
}
World* Session::getWorld() {return w;} //Returns a pointer to the current world
GraphicsManager.h
#pragma once;
class GraphicsManager {
private:
void render();
public:
void run(); //Calls the render method repeatedly; no further declaration in this example
}
GraphicsManager.cpp
#include "GraphicsManager.h"
void GraphicsManger::render() {
World* w = Session::getSession()->getWorld(); //Get pointer to current world so it can be rendered
}
The render method is where I'm stuck. If I put #include "Session.h" into the GraphicsManager.h file, it gives me an error because apparently two header files cannot include each other. If I put a forward declaration at the beginning of GraphicsManager.h or GraphicsManager.cpp, Visual Studio tells me that incomplete types are not permitted.
This has been giving me a headache for weeks. I've made games in Java before and there this pattern was accepted. So how can I do this? If this structure is not possible in C++, do you have other suggestions for it?
In GraphicsManager.cpp, the compiler needs to know about the Session, so you have to #include "Session.h" which by the way includes GraphicsManager as well as World.
A forward definition will not be sufficient, as the compiler would not be able to check types of getSession()->getWorld() expression.
Apparently your GraphicsManager.h doesn't rely itself on the other definitions, so there should'nt be an issue here.
Try to include Session.h to GraphicsManager.cpp:
#include "Session.h"
void GraphicsManger::render() {
World* w = Session::getSession()->getWorld(); //Get pointer to current world so it can be rendered
}
This way Session class defenition will be visible for compiler in GraphicsManager.cpp, so it will not generate incomplite type error. On the other hand, Session.h is not included to GraphicsManager header, so there will no problem that both headers include each other.
Related
I want to use a class: class2, within a class: class1. From what I read, to prevent a circular dependency, one must forward declare class2 in class1.h and have it be a pointer. After calling a function from class2 in my class1.cpp file. I'm unable to call the variables within class2 without getting "Unable to read memory" or a nullptr.
Here's my code, thank you for the help:
//main.cpp
#include "Login.h"
#include <iostream>
using namespace std;
int main() {
Login login;
login.StartMenu();
cout << "ENDING" << endl;
system("pause");
return 0;
}
//Login.h (Class1)
#pragma once
#include <iostream>
using namespace std;
class GameManager;
class Login {
public:
void StartMenu();
private:
GameManager* manager;
};
//Login.cpp
#include "Login.h"
#include "GameManager.h"
void Login::StartMenu() {
manager->GameStart();
}
//GameManager.h (Class2)
#pragma once
class GameManager {
public:
void GameStart();
private:
int level = 1;
};
//GameManager.cpp
#include "Login.h"
#include "GameManager.h"
void GameManager::GameStart() {
cout << level;
}
Generally, it is a good idea to keep dependencies between headers to a minimum, and using pointers for classes that are only forward-declared is an established way to do that. This is good practice even if there are no circular dependencies because it can greatly reduce recompilation times in large projects.
Regarding your specific question: Essentially, the Login class, and especially the Login::StartMenu function, needs to know which GameManager instance to use. A pointer to that instance will be stored in manager. Ideally you can tell that at construction time of a Login instance via a GameManager * constructor argument:
#ifndef LOGIN_H
#define LOGIN_H
class GameManager;
/// This class handles the login procedure for a specific
/// game manager which must be provided to the constructor.
/// It cannot be copied (so it cannot be
/// in arrays) or default-constructed.
class Login {
public:
/// The constructor does nothing except initializing manager.
/// #param gmPtr is a pointer to the game manager
/// this instance is using.
void Login(GameManager *gmPtr)
: manager(gmPtr) { /* empty */ }
void StartMenu();
private:
GameManager* manager;
};
#endif // LOGIN_H
For completeness, here is how you would use it:
#include "Login.h"
#include "GameManager.h"
#include <iostream>
using namespace std;
int main() {
GameManager gm;
Login login(&gm); // <-- provide game manager to login
login.StartMenu();
cout << "ENDING" << endl;
system("pause");
return 0;
}
If that is not possible because the GameManager instance does not exist yet or is otherwise unknown during construction of a Login instance (for example, if you have an array of Login instances, whose elements must be default-constructed) you can provide the argument to the Login::StartMenu method. But the constructor argument is much preferred because you can then be sure that the class is functional in the rest of the code — this kind of "invariants" are the main reason why constructors exist.
It is certainly possible that you don't need to hold a pointer at all, if all functions get that pointer argument. Whether the Login class has a one-to-one relationship with a GameManager (in which case it simply holds a pointer to it) or not (in which case every function is told each time) is a design decision.
I have this problem:
Problem:
I am trying to create a library (ard33WiFi) that manages and handles
a couple of other libraries (WiFiServer library for example)
I need to create the server object that I then use in functions in my Library (ard33WiFi):
WiFiServer myServer(iPort);
The problem is that when I call myServer in the members of the class I get:
'myServer' was not declared in this scope
Where/how do I declare myServer so that is becomes available to the entire class (ard33WiFi)? I have taken out any decleration because whatever I was trying was wrong. I have pasted a skeleton code below.
// HEADER FILE (.h)
// ----------------------------------------------------------------------------------------------
#ifndef Ard33WiFi_h
#define Ard33WiFi_h
#include <WiFiNINA.h>
#include <WiFiUdp.h>
class ard33WiFi{
public:
ard33WiFi(int iPort)
void someFunction();
void serverBegin();
private:
int _iPort;
};
#endif
// ----------------------------------------------------------------------------------------------
// C++ FILE (.cpp)
// -----------------------------------------------------------------------------------------------
#include <Ard33Wifi.h>
ard33WiFi::ard33WiFi(int iPort){
_iPort = iPort;
}
void ard33WiFi::someFunction(){
// code here required to prepare the server for initializing
// but ultimately not relevant to the question
}
void ard33WiFi::serverBegin(){
myServer.begin();
Serial.println("Server Online");
}
I run into the same problem with the UDP library as I need to call the UDP object in various functions to do UDP things.
Any help would be greatly appreciated.
I suppose you are using this:
https://www.arduino.cc/en/Reference/WiFiServer
I can see that you are not declaring the myServer in your class; that I guess is the error in your code. If I am not wrong, it should be something like this:
#ifndef Ard33WiFi_h
#define Ard33WiFi_h
#include <WiFiNINA.h>
#include <WiFiUdp.h>
#include <WiFi.h> // Not sure if you have to append this include
class ard33WiFi{
public:
ard33WiFi(int iPort)
void someFunction();
void serverBegin();
private:
int _iPort;
WiFiServer myServer;
};
#endif
The implementation, you would need to initialise the instance:
#include <Ard33Wifi.h>
ard33WiFi::ard33WiFi(int iPort):myServer(iPort), _iPort(iPort) {
}
void ard33WiFi::someFunction(){
// code here required to prepare the server for initializing
// but ultimately not relevant to the question
}
void ard33WiFi::serverBegin(){
myServer.begin();
Serial.println("Server Online");
}
This question comes from this question.
Im trying to implement the state pattern with a shared_ptr to the container(game).
However I have a problem with circular inclusion and need to forward declare.
My code:
Game.h
#pragma once
#include <memory>
#include "BaseState.h"
class Game : public std::enable_shared_from_this<Game>
{
private:
std::shared_ptr<BaseState> currentState;
public:
Game();
void switchState(std::shared_ptr<BaseState> nextState);
void doSomething(char);
void runState();
};
cpp
#include "stdafx.h"
#include <iostream>
#include "Game.h"
#include "SomeState.h"
Game::Game()
{
currentState = std::make_shared<SomeState>();
}
void Game::switchState(std::shared_ptr<BaseState> nextState)
{
currentState = nextState;
}
void Game::doSomething(char c)
{
std::cout << "Game : " << c;
}
void Game::runState()
{
currentState->handleCommand(shared_from_this());
}
BaseState.h
#pragma once
#include <memory>
#include "Game.h"
class BaseState
{
public:
virtual void handleCommand(std::shared_ptr<Game>) = 0;
};
SomeState.h
#pragma once
#include "BaseState.h"
class SomeState :
public BaseState
{
public:
// Inherited via BaseState
virtual void handleCommand(std::shared_ptr<Game>) override;
};
cpp
#include "stdafx.h"
#include "SomeState.h"
void SomeState::handleCommand(std::shared_ptr<Game> game)
{
game->doSomething('S');
}
I read other questions about forward declaring but still don't get it.
What I tried;
forward declare BaseState in Game, the code compiles but throws an error.
Unhandled exception at 0x73E9DAE8 in ConsoleApplication1.exe:
Microsoft C++ exception: std::bad_weak_ptr at memory location
0x00BBF5D4.
Forward declare Game in BaseState. Dosnt compile gives use of undefined type error, also
'doSomething': is not a member of
'std::shared_ptr'
which is logic because at compile time game has not a doSomething function because forward declared like;
class Game;
How do I decide where to forward declare another class, are there any logical steps or should I just pick one and fix the problems that choise creates?
You don't need to #include <Game.h> in BaseState.h, you can simply forward-declare it
class Game;
This works because the BaseState declaration doesn't need to know the contents of Game. So what you tried first is OK. The same applies to #include <BaseState.h> in Game.h. Replace that with a forward-declaration of BaseState.
The std::bad_weak_ptr exception was due to something else. Specifically, you're probably missing the little detail about shared_from_this, which says
It is permitted to call shared_from_this only on a previously shared
object, i.e. on an object managed by std::shared_ptr. Otherwise the
behavior is undefined
and
(from C++17) std::bad_weak_ptr is thrown (by the
shared_ptr constructor from a default-constructed weak_this)
You can usually solve this by instantiating your object into a shared_ptr:
int main() {
auto myGame = std::make_shared<Game>();
. . .
myGame->runState();
. . .
}
EDIT
Keep in mind though, that shared_ptr has a certain cost associated with using it. In general, if you know the pointed-to object always outlives the function call where it is used, as might be the case with your BaseState::handleCommand, then it may be faster (and still safe) to just pass it by reference.
Stupid question probably, but I couldn't find the answer (even here).
I have split all my classes in separate files (cpp+h). I have methods like getValue() and setValue(). I have class called Player (this is basically the database with whole number of variables). I created an object called player (Player *player = new Player;). Now I need to access THIS object from any other class (that separated in another file). The problem is that I cannot even access getValue() / setValue() methods.
What I need is something like in Delphi From1.player.item[0]=3 access from form 2, where the player is recorded.
UPD:
Here's my code:
Player.cpp
#include "player.h"
#include "gameform.h"
Player::Player()
{
}
void Player::check(){
//I should be able to check if player dead or not from my Battle class
}
player.h
#ifndef PLAYER_H
#define PLAYER_H
class Player
{
public:
Player();
void check();
};
#endif // PLAYER_H
Battle.cpp
#include "battle.h"
#include "player.h"
#include "game.h"
Battle::Battle()
{
}
void Battle::hit(){
//if I hit I should check am I dead yet
player.check();
}
That's how Player declared in Game class (now):
Player *player = new Player;
Outside of any functions, just in class.
Where player is object, created in Game class. All things are public.
*I've tried even creating object in main.cpp (both in and out of main() function), and nothing working, weird =/
This is github "temp" branch, compiling and working. But how to access player? :)
https://github.com/ewancoder/game/tree/temp
UPD: Another stupid question: If I want that in my class 1 function is responsible for opening file and another - for editing and closing file, how can I do that if one cannot read vars from another?
I'm not sure what you want, but if you have a class like this:
a.hpp
Class A {
public:
void foo();
};
a.cpp
#include "a.hpp"
void A::foo() {}
You can use it like this:
b.hpp
#include "a.hpp"
class B {
public:
void stuff(A& a);
};
b.cpp
#include "b.hpp"
void B::stuff(A& a) { a.stuff(); }
You need to give the other object the reference of the first. Either direct in the constructor or later via a method.
Or alternativly you could store player in a global variable and access it via the global variable.
The problem is that the methods are bound to the specific instance of the object - and so you need that instance to call them
You need to add parenthesis to the end of the statement and use the -> operator, not the . operator: player->check()
This is because it is a pointer to an object Player *player and not an object itself Player player
Your question is a little hard to follow, and some of the answers reflect that. However, in my view what you are running into is actually a critically important part of your system design. There are many strategies, and many considerations, but basically it's up to you to design the paths by which objects can access the contents of other objects in your running program.
Some common techniques include
Global variables
extern Player *PlayerOne;
PlayerOne->item[0]=3;
Static variables (or collections) in the class.
class Player {
public:
Player* Players;
}
Player::Players[0]->item[0]=3;
Member variables.
Board.Add(new Player(Board));
Board.m_player->item[0]=3;
The variations are endless. You'll need to be more specific if you want specific code.
I've been getting weird compile errors all over the place in a simple hunter/prey simulation (mostly because the professor hasn't explained the syntax for inherited classes and virtual functions very well) and I'm completely stuck on one issue. In this program, "Creatures" (an abstract class with "Hunter" and "Prey" children) walk around a "Grid" class in a Move(), Breed(), Die() cycle.
I'm getting the following errors: "C2027: use of undefined type 'Creature'" and "C2227: left of '->face' must point to class/struct/union/generic type" at the line specified in below (all my code's in the header because several students were getting unresolved externals in another project and the professor told us to just put it all in the headers). Let me know if I need to post more code.
I've gotten several other errors that I couldn't explain before this that seemed to be solved through a seemingly random combination of adding/removing included headers and pre-declaring classes, but an actual explanation of what's going wrong would be much appreciated so I'm not just flailing in the dark until it works. I understand the concept of what we're trying to do and even how to go about it for the most part, but as I mentioned, we didn't spend any time on the syntax of how to properly set up multiple files so that everyone works smoothly so any detailed explanation of how this should be done would be greatly appreciated.
Grid.h
#ifndef GRID_H
#define GRID_H
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include "Constants.h"
#include "creature.h"
using namespace std;
class Creature;
class Grid
{
public:
Creature* grid[MAX_X][MAX_Y];
Grid() //Initalizes the grid and spawns random creatures
{
for(int i = 0; i < MAX_X; i++)
for(int j = 0; j < MAX_Y; j++)
grid[i][j] = NULL;
}
void Move() //Tells each creature on the grid to move
{
//Call creature.Move() on each cell (if not NULL)
}
void Breed() //Tells each creature to breed (if it can)
{
//Call creature.Breed() on each cell (if not NULL)
}
void Kill() //Tells each creature to die (if it's old)
{
//Call creature.Die() on each cell (if not NULL)
}
char** Snapshot() //Creates a char array "snapshot" of the board
{
//Produces a 2D char array of the grid for display
}
Creature* Get(Coords here) //Returns a pointer to the object at the specified position
{
return grid[here.x][here.y];
}
char Occupant(Coords here) //Returns the character of the specified position
{
if(!Get(here))
return FACE_EMPTY;
Creature* temp = Get(here);
return temp->face; //*** ERRORS APPEAR HERE ***
}
void Clear(Coords here) //Deletes the object at the specified position
{
if(Get(here))
delete Get(here);
grid[here.x][here.y] = NULL;
}
};
#endif // GRID_H
creature.h
#ifndef CREATURE_H
#define CREATURE_H
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include "Constants.h"
#include "coords.h"
#include "grid.h"
using namespace std;
class Grid;
class Creature
{
public:
Grid* theGrid;
Coords position;
int stepBreed;
int stepHunger;
char face;
Creature(Grid* _grid, Coords _position, char _face) //Constructor
{
theGrid = _grid;
position = _position;
face = _face;
stepBreed = stepHunger = 0;
}
virtual Coords Move() = 0; //Allows the child to define it's own movement
virtual Coords Breed() = 0; //Allows the child to define it's own breeding
virtual bool Starve() = 0; //Allows the child to starve of its own accord
};
#endif // CREATURE_H
Your use of class Creature at the top of the file seems to indicate that you don't have access to the complete definition of Creature in this file. That makes it impossible for the compiler to do the -> operation on it - it doesn't know what the members of that class are! You need to have a complete definition of Creature in the same translation unit as this code. That is, Creature needs to be a complete type if you want to use it in this way.
Edit: Thanks for posting creature.h. Your problem (as mentioned in the comments below) is that you have a circular dependency problem. creature.h includes grid.h and vice versa. You'll need to break one of those links to get things working properly. In this case, removing #include "grid.h" from creature.h should do the trick - no code in creature.h depends on Grid being a complete type.