Passing an enum as a parameter - c++

I have a Weapon.h/cpp class. thats has an enum
Weapon.h
enum WEAPONTYPE {
LASER,
ROCKET
}
and I have a variable that I'd like to use to track the current enum.
WEAPONTYPE currentWeapon;
I have a function that will be called to change the currentWeapon value. The declaration in the header file is:
void weaponSelect(WEAPONTYPE choice);
and the declaration in the .cpp file is
void Weapon::weaponSelect(Weapon::WEAPONTYPE enumChoice)
{
currentWeapon = enumChoice;
}
Now the error I recieve is:
error C2511: 'void Weapon::weaponSelect(Weapon::WEAPONTYPE)' : overloaded member function not found in 'Weapon'
Any help is appreciated.
Edit 1:
Weapon.h
#ifndef WEAPON_H_
#define WEAPON_H_
class Weapon
{
public:
Weapon(Ogre::SceneManager* localManager);
virtual ~Weapon(void);
void createBullet(Ogre::Vector3 cameraPosition); //Create bullet nodes/entities.
void weaponSelect(WEAPONTYPE enumChoice); //Function to select weapon type. Tried to have "WeaponType enumChoice" as parameter but would produce error.
void updateBullet(); //Update bullet logic.
enum WEAPONTYPE {
LASER = 0,
ROCKET = 1
};
private:
WEAPONTYPE currentWeapon; //Enum var to track weapon selected.
Ogre::SceneManager* localBulletSceneManager; //Pointer to our application's scene manager
std::vector<Ogre::SceneNode*> bullets; //List of pointers to the bullet nodes.
};
#endif
Weapon.cpp
#include "Weapon.h"
#include <OgreStringConverter.h>
using Ogre::SceneNode;
using Ogre::Entity;
using Ogre::String;
using Ogre::Vector3;
Weapon::Weapon(Ogre::SceneManager* localManager)
: localBulletSceneManager(nullptr)
, currentWeapon(LASER)
{
this->localBulletSceneManager = localManager;
}
Weapon::~Weapon(void)
{
}
void Weapon::weaponSelect(WEAPONTYPE enumChoice)
{
this->currentWeapon = enumChoice;
}
void Weapon::createBullet(Vector3 cameraPosition)
{
//Pointers to use for Quick Node and Entity Creation - Get Reused once object is attached to scene.
SceneNode* tempNode = nullptr;
Entity* tempEntity = nullptr;
//All our Objects are spheres, so create one mesh and reuse it with each entity.
String bulletMesh = "Bullet";
//Procedural::SphereGenerator().setRadius(1.f).setUTile(5.).setVTile(5.).realizeMesh(bulletMeshName);
Procedural::ConeGenerator().setRadius(0.5F).setHeight(3.0F).realizeMesh(bulletMesh);
for (int bulletAmount = 0; bulletAmount < 10; ++bulletAmount)
{
tempNode = this->localBulletSceneManager->getRootSceneNode()->createChildSceneNode("RocketNode" + Ogre::StringConverter::toString(bulletAmount));
tempEntity = this->localBulletSceneManager->createEntity("RocketEntity" + Ogre::StringConverter::toString(bulletAmount), bulletMesh);
//tempEntity->setMaterial(
tempNode->attachObject(tempEntity);
tempNode->setPosition(0,0,100 + (bulletAmount * 10));
}
switch (this->currentWeapon)
{
case LASER:
break;
case ROCKET:
break;
}
}
Edit 2:
Reverted declaration for void weaponSelect in both .h and .cpp to the original version without any changes suggested by other posters.

Move your WEAPONTYPE declaration on the top of the class:
class Weapon {
public:
enum WEAPONTYPE {
LASER = 0,
ROCKET = 1
};
Weapon(Ogre::SceneManager* localManager);
// ...
The error was cause by the fact that when the compiler read the line:
void weaponSelect(WEAPONTYPE enumChoice);
it couldn't figure out what WEAPONTYPE is. That happened because the declaration of the enum comes later in the class.
Also, I see you are using C++11: use enum class instead:
enum class weapon {
laser,
rocket
};

If WEAPONTYPE is declared outside the class use this syntax:
void Weapon::weaponSelect(WEAPONTYPE enumChoice)
{
currentWeapon = enumChoice;
}
If this enum is declared within the class:
void Weapon::weaponSelect(Weapon::WEAPONTYPE enumChoice)
{
this->currentWeapon = enumChoice;
}
You must declare the enum before using it.

try moving the enum, WEAPONTYPE to be before the deceleration of weaponSelect
Also, I dont understand your API:
On one hand, you declare weaponSelect as public. But, it's parameter is a protected enum. how cau users of your class can use it? this should all have the same accessibility/.

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

Event-based Game engine based on polymorphism of Entities

I would like to create a simple framework for throwing and catching events in a game. Events could be things like a Collision which (according to the type) can take several arguments (note that every Event type may take another amount of arguments, not just two as in the example).
I would then like to implement functions/classes/... to deal with a Collision, based on polymorphism. This example should illustrate the problem:
#include <iostream>
#include <vector>
class Entity {};
class Player: public Entity {};
class Bomb: public Entity {
public:
bool exploded;
};
class MineSweeper: public Entity {};
// For now, I only included Collisions, but I eventually want to extend it to
// more types of Events too (base class Event, Collision is derived class)
void onCollision(Player* p, Bomb* b) {
if (! b->exploded) {
std::cout << "BOOM";
b->exploded = true;
}
}
void onCollision(Entity* e, Entity* f) {
std::cout << "Unhandled collision\n";
}
// Possibility for Collision between Minesweeper and Bomb later
class Game {
public:
std::vector<Entity*> board; // some kind of linear board
Game() {
board = {new Player, new Bomb, new MineSweeper};
}
void main_loop() {
onCollision(board[0], board[1]); // player and bomb!
onCollision(board[1], board[2]);
}
};
int main() {
Game g;
g.main_loop();
}
Note that I understand perfectly well why the above code doesn't work as intended, I included this example solely to illustrate my problem better.
The above example uses functions for the events, but I'm perfectly fine with classes or any other solution that is maintainable.
I hope it is clear that I would like C++ to decide which event handler to use based on the types of the arguments (presumably at runtime).
My question: How can I do this in C++? An example would be appreciated.
(not my question: fix my code please)
user2864740 provided enough clues for me to find a solution myself. Multiple dispatch was indeed the missing piece.
The following code works as intended, making use of dynamic_cast to dispatch correctly.
#include <iostream>
#include <vector>
class Entity {
virtual void please_make_this_polymorphic() {}
// although this function does nothing, it is needed to tell C++ that it
// needs to make Entity polymorphic (and thus needs to know about the type
// of derived classes at runtime).
};
class Player: public Entity {};
class Bomb: public Entity {
public:
bool exploded;
};
class MineSweeper: public Entity {};
// For now, I only included Collisions, but I eventually want to extend it to
// more types of Events too (base class Event, Collision is derived class)
void onCollision(Player* p, Bomb* b) {
if (!b->exploded) {
std::cout << "BOOM\n";
b->exploded = true;
}
}
void onCollision(Entity* e, Entity* f) {
std::cout << "Unhandled collision\n";
}
void dispatchCollision(Entity* e, Entity* f) {
Player* p = dynamic_cast<Player*>(e);
Bomb* b = dynamic_cast<Bomb*>(f);
if (p != nullptr && b != nullptr) {
onCollision(p, b); // player and bomb
} else {
onCollision(e, f); // default
}
}
class Game {
public:
std::vector<Entity*> board; // some kind of linear board
Game() {
board = {new Player, new Bomb, new MineSweeper};
}
void main_loop() {
dispatchCollision(board[0], board[1]); // player and bomb
dispatchCollision(board[1], board[2]);
}
};
int main() {
Game g;
g.main_loop();
}
Although it works, I'd like to point out some problems with this code:
Manual editing of dispatchCollision needed when adding new Collisions.
Currently, the dispatcher using a simple kind of rule-based system. (Does it fit rule 1? What about rule 2? ...) When adding loads of different functions it needs to dispatch, that may have an impact on the performance.
A collision between A and B should be the same as a collision between B and A, but that isn't properly handled yet.
Solving these problems is not necessarily in the scope of this question IMHO.
Also, the example given should work just as well for more than 2 arguments. (Multiple dispatch, not just double dispatch.)
You should decide first what event subscription model you need.
It could be signal/slot mechanism and you can find plenty of libraries:
https://code.google.com/p/cpp-events/ , http://sigslot.sourceforge.net/ and the like.
Or it could be bubbling/sinking events like in HTML DOM when event gets propagated on parent/child chain ( from event source element to its containers).
Or even other schema.
It is quite easy to create whatever you need with std::function holders in modern C++.
Maybe a good structure for your case could be something like this:
class Entity{
public:
virtual int getType() = 0;
};
enum EntityTypes {
ACTOR,
BOMB,
MINESWEEPER,
};
class Actor : public Entity{
public:
virtual int getType() {return int(ACTOR);}
void applyDamage() {
std::cout << "OUCH";
}
};
class Bomb : public Entity{
public:
Bomb() : exploded(false) {}
virtual int getType() {return int(BOMB);}
void explode() {
this->exploded = true;
}
bool isExploded() {
return this->exploded;
}
protected:
bool exploded;
};
class MineSweeper : public Entity{
public:
virtual int getType() {return int(MINESWEEPER);}
};
class CollisionSolver {
public:
virtual solve(Entity* entity0, Entity* entity1) = 0;
};
class ActorBombCollisionSolver : public CollisionSolver {
public:
virtual solve(Entity* entity0, Entity* entity1) {
Actor* actor;
Bomb* bomb;
if (entity0->getType() == ACTOR && entity1->getType() == BOMB) {
actor = static_cast<Actor*>(entity0);
bomb = static_cast<Bomb*>(entity1);
}else if (entity1->getType() == ACTOR && entity0->getType() == BOMB) {
actor = static_cast<Actor*>(entity1);
bomb = static_cast<Bomb*>(entity0);
}else {
//throw error;
}
if (!bomb->isExploded()) {
bomb->explode();
actor->applyDamage();
}
}
};
class CollisionDispatcher {
public:
CollisionDispatcher() {
CollisionSolver* actorBombCollisionSolver = new ActorBombCollisionSolver;
this->solvers[ACTOR][BOMB] = actorBombCollisionSolver;
this->solvers[BOMB][ACTOR] = actorBombCollisionSolver;
// this part wouldn't be necessary if you used smart pointers instead of raw... :)
this->solvers[BOMB][MINESWEEPER] = 0;
this->solvers[MINESWEEPER][BOMB] = 0;
this->solvers[ACTOR][MINESWEEPER] = 0;
this->solvers[MINESWEEPER][ACTOR] = 0;
}
void dispatchCollision(Entity* entity0, Entity* entity1) {
CollisionSolver* solver = this->solvers[entity0->getType()][entity1->getType()];
if (!solver) {
return;
}
solver->solve(entity0, entity1);
}
protected:
unordered_map<int, unordered_map<int, CollisionSolver*> > solvers;
};
class Game {
public:
std::vector<Entity*> board; // some kind of linear board
Game() : dispatcher(new CollisionDispatcher)
{
board = {new Player, new Bomb, new MineSweeper};
}
void main_loop() {
dispatcher->dispatchCollision(board[0], board[1]);
dispatcher->dispatchCollision(board[0], board[2]);
dispatcher->dispatchCollision(board[1], board[2]);
}
protected:
CollisionDispatcher* dispatcher;
};
int main() {
Game g;
g.main_loop();
}
This way you can easily add new collision solvers, just define the class, and register t in the CollisionDispatcher constructor.
If you use smart pointers you won't need to set zeroes in the map entries not registered, but if you use raw pointers you have to set them to zero OR use unordered_map::find method instead of just grabbing the solver using operator []
Hope it helps!

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.

how to define an enumeration inside a class and use it from the outside

Just because I don't know exactly where to look this up in my c++ book, or on google. How do I actually define some enumerations(in this case { left=1, right=2, top=3, bottom=4 }) inside a class. I want to be able to pass this enumeration as a parameter to member functions instead of an integer, therefore using the enumeration externally...
Is there a way I can do this, or is there a better way I which I can make the enumeration specific to that class only?
Here's the code that's not working, saying enum mySprite::<unamed> myySprite::side member mySprite "mySprite::side" is not a type name for some reason:
class mySprite : public sf::Sprite
{
public:
enum{left=1, right=2, top=3, bottom=4} side;
float GetSide(side aSide){
switch(aSide){
// do stuff
}
};
};
The simplest change needed to get your code to work is this:
class mySprite : public sf::Sprite
{
public:
enum side{ left=1, right=2, top=3, bottom=4 };
float GetSide(side aSide)
{
switch(aSide)
{
// do stuff
// add breaks; as appropriate
case left:
case right:
case top:
case bottom:
}
}
};
You can also do it this way:
typedef enum {left = 1, right, top, bottom} side;
Which means define an anonymous enum type for your mySprite class and make side an alias effectively accomplishing the same thing as the code above. For terseness only the first enum value needs to be assigned a starting integer. All values that come after that point are understood to be incremented by 1 each time unless you explicitly assign it something else.
I think this example explains it all:
class A {
public:
enum directions { top, left, right, bottom }; // directions is the type
// of the enum elements
void f(directions dir) {
if (dir == left) {
// ...
} else {
// ...
}
}
};
A object;
object.f(A::top);
You need to define it as a type to use it outside the class and/or strongly-type the parameter. Otherwise it is simply defined as an int, its access modifier must also be public:
class foo {
public:
typedef enum DIRECTION {
LEFT = 1,
RIGHT,
TOP,
BOTTOM,
};
void SetDirection(foo::DIRECTION dir) {
_direction = dir;
}
//...
protected:
//...
private:
foo::DIRECTION _direction;
//...
};
int main() {
//...
foo bar;
bar.SetDirection(foo::BOTTOM);
//...
}

Getting undefined class type error but I did create the class and defined it

Im working on an assignment for one of my classes. Simply I have a GumballMachine class and a bunch of State classes that change the state of the GumballMachine.
Here is the offending code:
class GumballMachine;
class State {
public:
virtual void insertQuarter() const = 0;
virtual void ejectQuarter() const = 0;
virtual void turnCrank() const = 0;
virtual void dispense() const = 0;
protected:
GumballMachine *GBM;
};
class NoQuarterState : public State {
public:
NoQuarterState (GumballMachine *GBM) {
this->GBM = GBM;
}
void insertQuarter() const {
cout << "You inserted a quarter\n";
**this->GBM->QuarterInserted();** // <--- C2027 error on MSDN
}
};
Now further below I have defined my GumballMachine class as:
class GumballMachine {
public:
GumballMachine(int numOfGB) {
this->noQuarterState = new NoQuarterState(this);
this->soldOutState = new SoldOutState(this);
this->hasQuarterState = new HasQuarterState(this);
this->soldState = new SoldState(this);
this->winnerState = new WinnerState(this);
this->count = numOfGB;
if (0 < numOfGB) {
this->state = this->noQuarterState;
}
else {
this->state = this->soldOutState;
}
}
... more code ...
void QuarterInserted() {
this->state = this->hasQuarterState;
}
... more code ...
protected:
int count;
NoQuarterState *noQuarterState;
SoldOutState *soldOutState;
HasQuarterState *hasQuarterState;
SoldState *soldState;
WinnerState *winnerState;
State *state;
};
Visual Studios was throwing a C2259 and C2027 error but after looking at MSDN I feel like I am doing it right. Maybe I am just tired, but I can't seem to find the error/see what I did wrong.
Much thanks to any help. :D
You cannot access any members of GumballMachine before you define the class, so you'll have to either split your file into several files, each containing one class, or define your NoQuarterState::insertQuarter method after the definition of the GumballMachine class:
class NoQuarterState : public State {
public:
NoQuarterState (GumballMachine *GBM) {
this->GBM = GBM;
}
void insertQuarter() const; // Declaration only
};
class GumballMachine {
public:
...
};
void NoQuarterState::insertQuarter() const {
cout << "You inserted a quarter\n";
this->GBM->QuarterInserted(); // Works now bec. comp. has seen the def.
}
GumballMachine class is missing a semicolon after its definition.
Chris, you need to adopt a more standard approach of splitting declarations into header files and definitions into module files.
class State needs to be in something like State.h and things like the definition of NoQuarterState::insertQuarter() needs to be in State.cpp.
When that is done you will know which .cpp files need to #include other header files to make them compile.
You are right to have class GumballMachine; before the declaration of class State since both State and NoQuarterState need to know that name.
class GumballMachine; declares the class. If you wish to dereference a pointer to an object of the class, you must first define the class. This is usually done in header files. In the class definition must declare all of it's member functions and variables, but you may define those functions wherever you like.