I'm pretty new to C++ and I am working in a little roguelike game. I have a generic class named Actor, which has 2 child classes, NPC and Player. The idea is for each child to contain specific data, such as experience provided by killing an NPC or the Player's stats, and special methods. On the other hand, Actor contains general methods such as move, because both player and NPC should move.
Now I have a vector of NPC pointers, and my move method should check if the target tile is occupied by an NPC (and some other NPC info), but I don't have access to that class from Actor. I added a forward declaration to NPC inside of Actor, but then I get this error:
pointer to incomplete class type is not allowed
because forward declaration is not enough to access NPC methods.
Actor.h:
class NPC; // Forward declaration.
class Actor
{
public:
void move(std::vector<std::unique_ptr<NPC>> & NPCs);
}
Actor.cpp:
void Actor::move(std::vector<std::unique_ptr<NPC>> & NPCs)
{
// Go through the NPCs.
for (const auto &NPC : NPCs)
{
if (NPC->getOutlook() > 0) ... // Error.
}
}
I could put the move method inside both NPC and Player, but I would be duplicating code, and that's a pretty bad idea.
What would be the best solution here? I guess there is a better way to organize this, but it seems pretty logical as it is. Maybe some kind of inheritance or virtual functions magic?
Thanks! :)
You will need to include the header where NPC is defined in Actor.cpp, otherwise the definition of NPC will be missing.
// Actor.cpp
#include "NPC.h"
void Actor::move(std::vector<std::unique_ptr<NPC>> & NPCs)
{
// Go through the NPCs.
for (const auto &NPC : NPCs)
{
if (NPC->getOutlook() > 0) ... // Now you'll be able to access this.
}
}
Related
I'm creating a third person laser tag shooter thing for fun and I'm having difficulty creating my weapon hierarchy. My main problem is my editor is crashing from an access error from some errors from pointers in my code and I don't understand pointers enough to be able to figure this out myself.
I'm trying to add a weapon to my default pawn ALTPlayer. I'm doing this by using TSubclassOf to ensure I can only attach children of ALTWeapon to my character
If it helps my explanation, current hierarchy is:
APawn->ALTWeapon->ALaserGun
... and I'm planning on adding a bunch more classes with ALTWeapon as their parent. I'm hoping this will make my code organized and easier to code different functionality for each weapon.
With that in mind, I'll start with my ALTPlayer.h file. Here I declare WeaponClass as my subclass variable
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "LTPlayer.generated.h"
class ALTWeapon;
UCLASS()
class LASERTAG_API ALTPlayer : public ACharacter
{
GENERATED_BODY()
public:
// Sets default values
ALTPlayer();
// Player weapon
UPROPERTY(EditAnywhere)
TSubclassOf<ALTWeapon> WeaponClass;
};
Now I'll move into my ALTPlayer.cpp file. Here I'm trying to create an ALaserGun object that's stored in WeaponClass. (I'm also not sure if this is exactly how I'm supposed to do this)
#include "LTPlayer.h"
#include "LaserGun.h"
// Sets default values
ALTPlayer::ALTPlayer()
{
// Creating Weapon
this->WeaponClass->GetDefaultObject<ALaserGun>();
}
At this point, I expect to see an ALaserGun component in my blueprint child of ALTPlayer. Although, since I have the pointer issue that's crashing my editor, I don't know if that's what this code produces.
If anyone has any insight on how to fix my pointers so that I don't get an access violation, that would be awesome!
You're attempting to dereference WeaponClass when you try to access its default object but it hasn't yet been assigned to anything.
You can initialize it in the constructor initializer list, like so:
ALTPlayer::ALTPlayer()
: WeaponClass(ALTWeapon::StaticClass())
{
}
If this is a class that can be set in a Blueprint default, you can also ensure that it has a value by setting it in PreInitializeComponents:
Declaration:
//~ Begin AActor Interface
virtual void PreInitializeComponents() override;
//~ End AActor Interface
Definition:
void ALTPlayer::PreInitializeComponents()
{
Super::PreInitializeComponents();
// Fallback to default Weapon class if none was specified.
if (WeaponClass == nullptr)
{
UE_LOG(LogGameMode, Warning, TEXT("No WeaponClass was specified in %s (%s)"), *GetName(), *GetClass()->GetName());
WeaponClass = ALTWeapon::StaticClass();
}
}
everyone. I'm working on a final project for school and it's coming along great, but I've run into a bit of a problem with trying to use a pointer to a pointer. I'll do my best to explain the problem below:
So I have a class called Player that sort of looks like this:
class Player
{
Player();
int health;
void adjustHealth(int);
};
Player::Player()
{
health = 40;
}
void Player::adjustHealth(int adjust)
{
health += adjust;
}
I have another class called Shelter, that include "Player.h" and looks a little like this:
class Shelter
{
Shelter();
Player* player; // Create a pointer to Player class.
};
In the Shelter header file, I have the following in my default constructor:
Shelter::Shelter()
{
...Other code here.
player = new Player();
}
In the Shelter header file, I use this new player for things like:
player->adjustHealth(-1); // Subtract one health from the player.
Which works great.
The problem I'm facing is with creating another class called Church, that is in a separate header file and acts as a separate location in the game. I want Church to use the same player that Shelter does, so it has all of the same stats, etc, rather than creating a new player in Church (which is what I did in Shelter.h).
Right now, I have something like:
class Church
{
Church();
Shelter **cplayer; // This is supposed to be the pointer to the pointer.
};
The default constructor is where I'm having my problem. I want to use the same player from Shelter, not create a new player like I did in Shelter.
Church::Church
{
What should I do here?
}
I've tried a number of things, but I can't quite get it working. Eventually I want to be able to do something like this:
player->adjustHealth(-1); // Subtract one health from the player.
Only in Church, so that player's stats, like health, are adjusted no matter which location they are in.
I hope my question makes sense. If not, I can try to clarify better. Anyway, thanks in advance.
The problem I'm facing is with creating another class called Church, that is in a separate header file and acts as a separate location in the game. I want Church to use the same player that Shelter does, so it has all of the same stats, etc, rather than creating a new player in Church
This sounds like an ideal situation to use std::shared_ptr.
class Shelter
{
Shelter();
std::shared_ptr<Player> player; // Create a pointer to Player class.
// Provide a public accessor
public:
std::shared_Ptr<Player> getPlayer() const { return player; }
};
and
class Church
{
Church(std::shared_ptr<Player> pl) : player(pl) {}
std::shared_ptr<Player> player;
// You haven't explained in your post why you need this.
// Maybe you don't need it.
// Shelter** shelter;
};
I'm learning C++ by programming a game. I'm using SDL to display my objects and a factory structure to keep it all organised.
I separated the first object (a car), the controls (keyboard) and the display (monitor).
In my main class I call the monitor class to display a window where I should draw the images. If a key is pressed, the car should react to that by redrawing the image.
The problem here is that I initialized the monitor in the main class and I can't access it in my car class..
I tried a variety of things, but nothing seems to do the trick.
So here is the main class
Game::Game(GuiFactory* factory) {
bool is_running = true;
Car* car = factory->createCar();
car->drawCar();
// create factory specific window
Monitor* monitor = factory->createMonitor();
// create factory specific keyboard
Keyboard* keyboard = factory->createKeyboard();
while (is_running) {
// keyboard input
string key_input = keyboard->getKeys();
if (key_input == "quit") {
is_running = false;
} else if (key_input != "") {
if(key_input == "right"){
car->turnRight(monitor);
}
}
}
}
I have a main car class and an SDLCar class, which inherits car.
class Car {
public:
Car();
virtual ~Car();
virtual void drawCar() = 0;
virtual void turnRight() = 0;
};
Here is where I'm confused:
class SDLCar : public Car {
public:
SDLCar();
virtual ~SDLCar();
void drawCar();
void turnRight(SDLMonitor& monitor);
// ^^^^^^^^^^^^^^^^^^^
};
Could someone please explain?
In your base class Car you have declared the method turnRight which takes no parameters.
In your derived class SDLCar you have declared a completely different method with the same name. The reason why it's a different method and not a function override is that its takes a parameter. It should be parameterless to override Car::turnRight.
And because it's not a function override, the rules of polymorphism don't apply. Thus you can't call SDLCar::turnRight(SDLMonitor&) from a Car pointer.
Right now is an excellent time to start using the override keyword. It prevents specifically these kind of programming errors. By marking a function with override:
void turnRight(SDLMonitor& monitor) override;
the compiler will automatically check that it actually overrides a function from the base class.
E.g. with the above declaration, the compiler would give you an error (or a warning at least). This would've helped you find your error right away and prevented more erroneous code such as car->turnRight(monitor).
So now that the error is found, you need to find a way to fix it. Either declare the base class turnRight to take a SDLMonitor& as well, or think of something else if that's not how it should behave.
IMO having to pass the game window to a method like turnRight seems weird. Why would turning a car need a window? I think turnRight should do just what it says on the tin: turn the car right. Nothing else.
I don't know why you're passing a window to the method but if it's for drawing, shouldn't the drawCar method handle that? I don't know your code, so I'll leave it up to you.
This question already has answers here:
Resolve build errors due to circular dependency amongst classes
(12 answers)
Cross referencing included headers in c++ program
(5 answers)
Closed 9 years ago.
For example a little Computergame with three Classes Player, Bot and Game
Player has a Method that checks if the Player collide with a bot
// Player.h
#include Game.h
#include Bot.h
class Player {
private:
bool collision(Game g) {
for (Bot bot: g.bots)
...
}
};
The Bot.h (kept simple, of cause it has some other attributes like actual position and so far)
// Bot.h
class Bot {
public:
Bot()
};
The Gameclass handles the Gameloop and the List of Bots
//Game.h
#include Bot.h
#include Player.h
class Game {
public:
Player player:
std::vector<Bot> bots
void loop() { player.collision() }
};
So here we have the problem that Game.h includes Player.h and the other way around.
How can I resolve this?
While the other answers here are certainly technically correct, whenever I come across a situation like this I see it as pointing out a potential flaw in my design. What you have is cyclic dependencies, like so:
This isn't just a problem for your implementation, it means that there is too much coupling between classes, or, conversely, too little information hiding. This means that you can't design the Player independently of the Game, for example.
So if possible, I'd prefer a situation like this, where the Game, as the controller delegates work out to other classes.
One way to do this is for the Game to pass references to its own properties as and when the Player needs them.
For example have collision take a bots parameter rather than the `Game
bool collision(const std::vector<Bot&> bots) {
// note pass objects by const ref is usu preferred in C++ to pass by value
for (Bot bot: g.bots)
...
}
(Note in a more sophisticated approach, it could pass interfaces, i.e. abstract base classes, onto itself).
If all else fails, you can go back to using a forward declaration.
In this case the easiest thing would be a forward declaration, and moving some code from the header file to the source file.
Like this
Player.h
#include "Bot.h"
class Game; // forward declaration
class Player {
private:
bool collision(Game g);
};
Player.cpp
#include "Player.h"
#include "Game.h"
bool Player::collision(Game g) {
for (Bot bot: g.bots)
...
}
The forward declaration tells the compiler that Game is the name of a class but nothing else. So the Player::collision method must be moved to the Player.cpp file where the full definition of Game is available.
I dont think you can do this since If A contains B, and B contains A, it would be infinite size. Infact you can create two classes that store pointers to one another, by using the forward declaration, so that the two classes know of each other's existence
Forward declaration is required - http://en.wikipedia.org/wiki/Forward_declaration
I'm currently developing an RPG game using C++ and I got to the point of including events on the map.
I wanted to be able to have the event on the map heal the player. I figured the easiest way to do this was to pass a pointer to the event object from the game using the 'this' keyword. When I got into doing this there were a whole bunch of compiler errors that seem to have resulted from trying to include a class that was currently attempting to include the other class. (endless loop I guess?)
For example. I have my 'game' class and it has a public member belonging to the 'mapManager' class. The 'mapManager' object then has the 'event' object as a member. The 'game' object also has a 'player' object within its' members. I need to have the 'event' object change variables that the 'player' has. I could honestly throw pointers whenever I need them but this might get cumbersome.
What I'm trying to ask is if there is an easy way to have a child of a parent access another child of that parent or if it would just be easier to throw pointers to all of the child classes needing them pointing to the other children.
Wow... that made very little sense but hopefully someone can understand enough to give me a good answer. Here's some code in case it helps.
:game.h
include "player.h"
include "event.h"
class game
{
public:
player Player;
event Event;
};
:player.h
class player
{
public:
game* Game;
};
:event.h
class event
{
public:
game* Game;
};
Having just this results in "game does not name a type" and so I tried to include game in event.h and player.h and got the same error. What I want to do is be able to access player's variable HP from inside event.
It's preferable to avoid circular references where possible; however if you really want to do that, then the solution is to forward-declare your class Game at the top of the header files which will be using references/pointers to it. e.g.
#ifndef EVENTH
#define EVENTH
class Game;
class Event
{
Game* game;
};
#endif
and..
#ifndef PLAYERH
#define PLAYERH
class Game;
class Player
{
Game* game;
};
#endif
For header files which need no knowlege of the implementation/sizeof the Game class, a simple forward-declaration is sufficient to let the compiler know that a class with that name exists.
In your .cpp source files (where the implementation of Game is actually important and used by Player/Event implementation) you will still need to #include the header containing your Game class definition.
//game.h
class event;
class game {
event _e;
private:
game(){}
//game& operator=(game& other) {}
~game(){}
public:
static game & getInstance() {
static game instance;
return instance;
}
event& getEvent() {return _e;}
};
//HealEventObserver.h
class HealEventObserver {
public:
virtual void heal() = 0;
virtual ~HealEventObserver(){}
};
//player.h include game.h and HealEventObserver.h event.h
class Player : public HealEventObserver
{
public:
virtual void heal() {/*heal the player*/}
Player() {
game& instance = game::getInstance();
event& e = instance.getEvent();
e.registerObserver(this);
}
};
//event.h include HealEventObserver.h
class event {
std::set<HealEventObserver*> _observers;
void notify() {
std::set<HealEventObserver*>::iterator it = _observers.begin();
std::set<HealEventObserver*>::iterator end = _observers.end();
for( ;it!=end; ++it) {
it->heal();
}
}
public:
void registerObserver(HealEventObserver* observer) {_observers.insert(observer);}
};
Don't make your event object change the player at all just make the event tell the player to heal himself. Also if game is suppose to represent everything then make it global.
To Answer the comment: (This is just my opinion and nothing else.)
After a bit of research i found this link that gives the names of great references.
The Definitive C++ Book Guide and List