Passing Enums Into Objects in Different Files - c++

So I am currently working on a text-based RPG, and I have run into an odd issue. In working on the weapon coding, I chose to go with enums for the type and rarity of the weapon. I have already programmed everything for my Weapon class; yet, when I try to create a Weapon object, I get an error having to do with my enums -- error: 'common' is not a type. The relevant code is as follows:
In Enum_Weapon.h:
#ifndef ENUM_WEAPON_H_INCLUDED
#define ENUM_WEAPON_H_INCLUDED
enum rarity{common, uncommon, rare, epic, legendary};
enum weaponType{axe, bow, crossbow, dagger, gun, mace,
polearm, stave, sword, wand, thrown};
#endif // ENUM_WEAPON_H_INCLUDED
And in Weapon.h:
#ifndef WEAPON_H
#define WEAPON_H
#include "Item.h"
#include "Enum_Weapon.h"
class Weapon : public Item{
public:
Weapon();
Weapon(rarity r, weaponType t, std::string nam, int minDam,
int maxDam, int stamina = 0, int strength = 0,
int agility = 0, int intellect = 0);
The code, of course, goes on; but this is all the code that is relevant to my error. Finally, when I try to create a Weapon object, I get the error:
#ifndef LISTOFWEAPONS_H
#define LISTOFWEAPONS_H
#include "Weapon.h"
#include "Enum_Weapon.h"
class ListOfWeapons
{
public:
ListOfWeapons();
protected:
private:
Weapon worn_greatsword(common, sword, "Worn Greatsword", 1, 2);
};
#endif // LISTOFWEAPONS_H
The same error also happens with the sword enum. I have researched the problem, but I can't find anything similar to the issue that I am having. Any help is much appreciated!

Your weapon attribute was a function declaration, not a variable definition. You must pass in default values in the constructor.
class ListOfWeapons
{
public:
ListOfWeapons() :
worn_greatsword(common, sword, "Worn Greatsword", 1, 2)
{
//...constructor stuff
}
protected:
private:
//function decl
//Weapon worn_greatsword(common, sword, "Worn Greatsword", 1, 2);
Weapon worn_greatsword;
};

Related

Using an enum from a Forward Declared Class

Current Problem:
I need to access an enum from a class that is forward declared, similar to this situation:
Human.h
#include "Dog.h"
class Human{
public:
enum Language: uint32_t {
None = 0,
English = 1,
Japanese= 2,
};
}
Dog.h
class Human;
class Dog{
void understand(Human::Language speech);
}
Dog.cxx
#include "Dog.h"
#include "Human.h"
void Dog::understand(Human::Language speech) {
// Do stuff with Human::Language
return;
}
Errors:
The IDE tells me Dog.cxx's implementation is not compatible with Dog.h's deceleration, citing the enum as <erro-type> in the error hint (only red squiggle)
When compiling, any mention of the enum in Dog.h/c.xx throws errors, not being able to find the enum
Extra Info:
MSVC 15 2017
Full architecture of program requires the enum to be accessible like this
Forward Deceleration is mandatory in order to solve a circular dependency within my program that is not seen here
Basically the answer is no, you can't forward declare the enum in this context. Your choices are:
Move the enum into a lightweight base class.
struct HumanBase
{
enum Language: uint32_t {
None = 0,
English = 1,
Japanese= 2,
};
};
//fwd declare
struct Human;
Move the enum out of the class.
enum HumanLanguage : uint32_t {
None = 0,
English = 1,
Japanese= 2,
};
struct Human;
and then if you need to later on, you can do:
struct Human
{
typedef HumanLanguage Language;
};
Change all the method that use the enum to be a template (which may work in some cases, possibly not in others)
class Dog{
template<typename LanguageType)
void understand(LanguageType speech);
};

Troubles with Circular Dependencies between 3 classes and with inheritance

I'm a first-year college student that doesn't know everything about CS yet, so please bear with my newness to it, and this is my first question on here.
For an assignment, we are making faux version of Pokemon Go to practice using polymorphism in c++, and I'm running into some compiler errors. Here are the three files with just a sample of the code in them:
#ifndef EVENT_H
#define EVENT_H
#include <string>
#include "Trainer.h"
class Event{
protected:
std::string title;
public:
Event();
~Event();
virtual void action(Trainer) = 0;
};
#endif
Trainer.h:
#ifndef TRAINER_H
#define TRAINER_H
#include "Pokemon.h"
class Trainer{
private:
Pokemon* pokemon;
int num_pokemon;
public:
Trainer();
~Trainer();
//include accessors and mutators for private variables
};
#endif
Pokemon.h:
#ifndef POKEMON_H
#define POKEMON_H
#include "Event.h"
#include <string>
class Pokemon : public Event{
protected:
std::string type;
std::string name;
public:
Pokemon();
~Pokemon();
virtual bool catch_pokemon() = 0;
};
#endif
The trainer.h file is a parent class for each pokemon type (eg Rock) which just defines a few virtual functions. The error I'm getting is when I'm compiling all of this and I get something that says:
Pokemon.h : 5:30: error: expected class-name befoer '{' token:
class Pokemon : Event {
Pokemon need to be a derived class to an event, so that an event pointer can point in another Location class can point to either a pokemon, pokestop, or cave for the assignment, and I have been looking online for hours and can't figure out what to do. I would appreciate the help! Let me know if you need more info or something because again, this is my first time posting a question.
You need some forward declarations.
In Event.h, you can put class Trainer; instead of #include "Trainer.h". In Trainer.h, you can put class Pokemon; instead of #include "Pokemon.h".
You will probably need to include the appropriate headers in the corresponding source files in order to actually use the other classes. But by avoiding the includes in the header files, you get out of the circular dependency trouble.
Pokemon.h must continue to #include "Event.h", since you're inheriting Event, which requires a complete definition.
Use forward declaration, to tell classes the type they need to use will be defined later. You can use forward declaration in situations where the size is know, pointers and references are always the same size regardless of the type they point to so use them.
#ifndef EVENT_H
#define EVENT_H
#include <string>
class Trainer;
class Event
{
protected:
std::string title;
public:
Event();
virtual ~Event();
virtual void action(Trainer* const trainer) = 0;
};
#endif
then
#ifndef TRAINER_H
#define TRAINER_H
class Pokemon;
class Trainer
{
private:
Pokemon* const pokemon;
int numPokemon;
public:
Trainer();
~Trainer();
};
#endif
then
#ifndef POKEMON_H
#define POKEMON_H
#include "Event.h"
#include <string>
class Pokemon : public Event
{
protected:
std::string type;
std::string name;
public:
Pokemon();
virtual ~Pokemon();
virtual bool catchPokemon() = 0;
};
#endif
when using polymorphism (virtual functions) you must always make the base class destructor virtual too. It is also nice to make the derived classes destructor virtual as well, but it is not required.

chess game - error in abstract class

#pragma once
#include <string>
#include <iostream>
using namespace std;
class Chess_tool
{
public:
Chess_tool(string color, char name);
virtual bool legal_movement(int source[], int dest[]) const = 0;
private:
string _color;
char _name;
};
Im trying to create chess game, so I create abstract class for chess tool (queen, king, rook...)
I also created king tool to check my code:
#pragma once
#include "Chess_tool.h"
class King : Chess_tool
{
public:
King(string color, char name);
virtual bool legal_movement(int source[], int dest[]);
};
and I create game_board class:
#pragma once
#include "Game_board.h"
#include "Chess_tool.h"
#include <iostream>
#define BOARD_SIZE 8
using namespace std;
class Chess_tool;
class Game_board
{
public:
Game_board();
~Game_board();
void move(string panel);
protected:
Chess_tool* _board[BOARD_SIZE][BOARD_SIZE];
};
the problem is here, when i try to add object to the matrix its show me error :
1 IntelliSense: object of abstract class type "King" is not allowed:
pure virtual function "Chess_tool::legal_movement" has no overrider
#pragma once
#include "Chess_tool.h"
#include "Game_board.h"
#include "King.h"
using namespace std;
enum Turn { WIHTE, BLACK };
class Manager : Game_board
{
public:
Manager();
~Manager();
virtual bool legal_movement(int source[], int dest[]) const = 0;
};
....
#include "Manager.h"
Manager::Manager()
{
_board[0][0] = new King();
}
The member function in the base class is const-qualified, not in the derived class.
So these are not the same functions through inheritance. You've declared a new virtual function, not overriden the first one.
Add const to the second one so that it actually override the base class function.
Remember that for virtual function overriding to kick in, there are a few condition to actually satisfy. They must have:
the same name
the same return type
the same parameters count and type
the same const-qualification (our case here)
a few other minor things (for example, compatible exceptions specifications)
If any condition isn't satisfied, you create a very similar, but different, function for the compiler.
With C++11, you should use override for the functions you want to override, so the compiler knows your intention and tells you that you've made a mistake. E.g.:
virtual bool legal_movement(int source[], int dest[]) override;
// ^^^^^^^^

C++ Compiler Error; Namespace issue I guess

The error I get is "No member named detail in namespace ChessGame. Here is the relevant code
//ChessPiece.h
namespace ChessGame
{
class ChessBoard;
namespace detail
{
class IChessPieceEnums{
public:
enum PieceType{PAWN, KNIGHT, BISHOP, ROOK, QUEEN, KING};
enum PieceDirection{ UP = 1 , DOWN = -1};
enum PieceId{ WHITE_PIECE_ID, BLACK_PIECE_ID };
};
}
//represents an abstract chess piece interface
class IChessPiece : public detail::IChessPieceEnums
{
public:
///...
}
} // end namespace
//GameBoard.h
#include "ChessPiece.h"
namespace ChessGame
{
class IChessPiece;
class ChessBoard
{
public:
/*********ERROR OCCURS ON THIS FUNCTION************/
bool isOccupiedWithEnemy(int row, int col,const ChessGame::detail::IChessPieceEnums::PieceId& pieceId);
}
}
Any idea guys?
EDIT: Another minimal example :
//Piece.h
#ifndef TestProject_C___Piece_h
#define TestProject_C___Piece_h
#include "Board.h"
namespace Foo {
namespace detail{
struct PieceEnums{
enum PieceID{ ID1, ID2 };
};
}
class Board;
class Piece{
public:
void foo(Board& b)const;
};
}
#endif
//board.h
#ifndef TestProject_C___Board_h
#define TestProject_C___Board_h
#include "Piece.h"
namespace Foo {
class Piece;
class Board{
bool isOcc(int x, int y,const detail::PieceEnums::PieceID pid)const;
};
}
#endif
And the error is 'Use of undeclared identifier detail
Note that this is across multiple files, so maybe its a problem with linkage?
To specify the desired name directly, say either detail::IChessPieceEnums::PieceId or ::ChessGame::detail::IChessPieceEnums::PieceId, but preferably the former. However, your present syntax is actually fine, too, since search resumes in the global namespace if a name can't be found.
Ok found a solution. The solution is to put the namespace detail in its own file called detail.h. That way, piece.h and board.h needs to include details.h to use it. That worked.
And the problem with the original post is that there is a circular reference. That is causing trouble somehow. Would love an explanation.

Inheritance error dilemma: "invalid use of incomplete type" VS "expected class-name"

So I'm trying to get class "Herder" to inherit from class "Mob". But I am getting compiler errors that read as follows:
error: invalid use of incomplete type 'struct Mob'
error: forward declaration of 'struct Mob'
This is what Herder.h looks like:
#ifndef HERDER_H_INCLUDED
#define HERDER_H_INCLUDED
#include <SFML/Graphics.hpp>
#include <cstdlib>
#include "Level.h"
#include "Mob.h"
class Mob;
class Herder : public Mob
{
public:
//Member functions.
Herder(Level* level, int x, int y);
void virtual GameCycle(sf::RenderWindow* App);
void virtual Die();
void Roar();
protected:
float m_RoarCountdown;
float m_RoarTime;
float m_Speed;
bool m_Roaring;
};
#endif // HERDER_H_INCLUDED
Figuring that it must be the class Mob; that is causing this, I remove it, but then I get the following error, refering to the line where the curly braces open:
error: expected class-name before '{' token
This is actually why I originally added the forward declaration - I had thought that the compiler wasn't recognizing Mob in class Herder : public Mob, so I figured I would forward declare.
I don't think it's a case of cyclical dependency, as has been the case in some cases I found via Google - "Mob.h" contains nothing to do with the Herder class whatsoever.
I have tried removing #include "Mob.h" altogether and sticking with just the forward declaration, but that doesn't work either - I get only one error, again:
error: invalid use of incomplete type 'struct Mob'
This is confusing. I've successfully gotten classes to inherit before, and this code seems analogous in all relevant ways to my previous successful attempts.
EDIT: Here are the contents of Mob.h
#ifndef MOB_H_INCLUDED
#define MOB_H_INCLUDED
#include <SFML/Graphics.hpp>
#include <cstdlib>
#include "Level.h"
class Level;
class Mob
{
public:
//Member functions.
Mob(Level* level, int x, int y);
float GetX();
float GetY();
void SetColor(sf::Color color);
void virtual GameCycle(sf::RenderWindow* App) = 0;
void virtual Die() = 0;
void Draw(sf::RenderWindow* App);
protected:
float m_X;
float m_Y;
bool m_Moving;
int m_Health;
sf::Sprite m_Sprite;
Level* pLevel;
};
#endif // MOB_H_INCLUDED
EDIT: Here are the contents of the "Level.h" file. Note that Baby is a child class of Mob in much the same way as Herder; both experience the same errors.
#ifndef LEVEL_H_INCLUDED
#define LEVEL_H_INCLUDED
#include <SFML/Graphics.hpp>
#include <cstdlib>
#include "Tile.h"
#include "Herder.h"
#include "Baby.h"
class Tile;
class Herder;
class Baby;
/// LEVEL
/// This is the collection of all data regarding a level, including layout, objects, mobs, and story elements.
///
class Level
{
public:
//Constructor
Level(int height, int width, std::string name);
//For obtaining positional data
int GetHeight();
int GetWidth();
std::string GetName();
sf::Image GetTileImage(int image);
sf::Image GetMobImage(int image);
std::vector< std::vector<Tile> >& GetGrid();
void NewHerder(int x, int y);
void NewBaby(int x, int y);
void GameCycle(sf::RenderWindow* App);
void GraphicsCycle(sf::RenderWindow* App);
private:
//Size
int m_Height;
int m_Width;
//Spatial coords
std::string m_Name;
//The grid of tiles.
std::vector< std::vector<Tile> > m_Grid;
//A vector of the images to be used for tiles.
std::vector<sf::Image> m_TileImages;
//A vector of the images to be used for tiles.
std::vector<sf::Image> m_MobImages;
//The herders
std::vector<Herder> m_Herders;
//The babies
std::vector<Baby> m_Babies;
};
#endif // LEVEL_H_INCLUDED
EDIT: Pre-emptively, here are the contents of Tile.h:
#ifndef TILE_H_INCLUDED
#define TILE_H_INCLUDED
#include <SFML/Graphics.hpp>
#include <cstdlib>
#include "Level.h"
class Level;
/// TILE
/// This is the basic environmental unit in the game
///
class Tile
{
public:
//Constructor
Tile(int col, int row, int size, int type, Level* level);
//For obtaining positional data
int GetX();
int GetY();
int GetRow();
int GetCol();
//For obtaining type data
int GetType();
//For obtaining string type data
std::string GetStringType();
//For changing type data
void SetType(int type);
void SetStringType(std::string character);
//For activities that regularly take place
void GameCycle();
//Draws the tile.
void Draw(sf::RenderWindow* App);
private:
//The level this tile belongs to.
Level* m_Level;
//Size (it's a square!)
int m_Size;
//Spatial coords
int m_X;
int m_Y;
//Grid coords
int m_Row;
int m_Col;
//Type
int m_Type;
//Visual data
sf::Sprite m_Tile;
};
#endif // TILE_H_INCLUDED
It is a cyclic dependency (Herder.h includes Level.h which includes Herder.h, etc.).
In Herder.h, simply replace this :
#include "Level.h"
with :
class Level;
and do the same in Mob.h
The general rule is to include as little header files as possible (ie. only the ones you need). If you can get by with a forward declaration eg., then use that rather than a full include.
The problem you have is a cyclic dependency which is a code smell. On the one side, to be able to derive from a type, the base definition must be available to the compiler (i.e. the compiler requires a fully defined type from which to inherit). On the other hand your base class depends on the derived class.
The technical answer is to forward declare the derived type (so that you can define the base), and then define the base. But you should really think on what you are doing: why are those two separate types related by inheritance? Why not one? Or three (split responsibilities)? If the base depends on the derived for it's own interface, that seems to indicate that they are too highly coupled. Rethink the design.
"Herder.h" and "Level.h" are #include in each other. So, I think this error is coming from the "Herder.h" which is included first. It's becoming cyclic. Remove that and see if the error goes away.