In C++, how can I declare an interface s.t. I can use it as shown below:
/** Enemy "Interface" */
Class Enemy {
Enemy();
virtual ~Enemy();
virtual void doStuff() = 0;
};
/** Enemy of type 1 */
Class Enemy_type1 : public Enemy {
Enemy_type1();
virtual ~Enemy_type1();
virtual void doStuff() {
// different for every type of enemy
}
};
/** Add an enemy to EnemyManager */
void EnemyManager::addEnemy(Enemy * e) {
this->enemies.push_back(*e); // declared as vector<Enemy> enemies;
}
First, you'll have to (or at least want to) make the functions that make up your interface public:
class Enemy {
public:
Enemy();
virtual ~Enemy();
virtual void doStuff() = 0;
};
Then you'll inherit from it (C++ doesn't have "interfaces" and "classes" as separate concepts).
class Emeny_type1 : public Enemy {
// ...
};
Finally, since these are polymorphic types, you'll want to create a collection of pointers to enemies, not of actual Enemy objects:
void EnemyManager::addEnemy(Enemy const *e) {
enemies.push_back(e);
}
This does raise the issues of object lifetime and ownership (which mostly aren't issues in Java). When you add an item to the collection, you'll need to ensure that it's not destroyed as long as you're going to use it, and is destroyed once you're done with it (e.g., when an enemy has been defeated, you might want to remove it). You need to decide whether the EnemyManager is going to delete enemies that are no longer needed, or some other code. If the EnemyManager is going to delete them, you may need (or want) to add a clone function to your Enemy interface for it to get a copy of the object being added to the collection.
Edit: based on your comment, you're not quite sure how to use the Enemy "interface" of a pointer you've stored in your collection. Fortunately, that's fairly simple, something like this:
for (int i=0; i<enemies.size(); i++)
enemies[i]->doStuff();
/* Enemy Interface (Abstract Base Class)
This goes in a header, say Enemy.hpp
*/
class Enemy {
public: // note default access is private in classes
Enemy();
virtual ~Enemy();
virtual void doStuff() = 0;
};
/* Add an enemy to EnemyManager.
The interface is a type, and is known!
It doesn't need to know anything about the subclasses
which implement the interface.
*/
void EnemyManager::addEnemy(Enemy * e) {
this->enemies.push_back(*e); // vector of Enemy POINTERS
}
/* Enemy of type 1.
This would go in say Enemy1.hpp - it depends on Enemy.hpp,
but EnemyManager doesn't need to know anything about this.
*/
Class Enemy_type1: public Enemy {
public:
Enemy_type1();
virtual ~Enemy_type1();
virtual void doStuff();
};
/* ... and in a .cpp file somewhere ... */
Enemy_type1::Enemy_type1() : Enemy()
{
// this is redundant unless you have some work for it to do
}
Enemy_type1::~Enemy_type1()
{
}
void Enemy_type1::doStuff()
{
// do your stuff here
}
Related
I've been coding a simple board game to learn concepts of C++ in practice. I have implemented the board: it consists of tiles, each of which is a child class inheriting from a parent class. The board is a class that has a vector of the tiles.
There are several kinds of tiles. Some of them can be bought by players. There are several different kinds of buyable tiles as well with different properties, so I deemed it cute to make a base class TileOnSale for tiles that can be bought and make child classes of the actual types, two of which I have provided in the below code.
Now my problem is that how can I access the child members' functions not defined within the parent class (TileOnSale)? Board gets initialized with all kinds of different tiles, so I can extract a Tile from there using getTile(int location) function. However, this gets interpreted as just a Tile, not a TileOnSale or a StreetTile. I know of no way to grasp StreetTile's buildHouses function this way.
So, is there a robust, or even better, a neat way of doing this? Can I make a template or something to hold Tile objects that might be StreetTiles or StationTiles or something else that is a Tile?
Or should I just redesign the class structure?
Here's a bare bones code. I have tried to provide only what is needed for understanding the question. Also, originally Tile and Board were in their own header files. I decided it not necessary to show the Player class that has a vector of owned TileOnSale objects but which retains the exact same access problem as Board.
// Board.h
#include "Tile.h"
typedef vector<Tile> Tiles;
class Board
{
public:
Board();
~Board();
Tile getTile(int location);
private:
Tiles tiles;
};
// Tile.h
class Tile
{
public:
Tile();
~Tile();
protected:
tileType tile_type; // this is enum containing unique type
string description;
};
class TileOnSale : public Tile
{
public:
TileOnSale();
~TileOnSale();
virtual int getRent() const { return 0; };
};
class StreetTile : public TileOnSale
{
public:
StreetTile();
~StreetTile();
int getRent() override;
void buildHouses(int number);
private:
int houses;
};
class StationTile : public TileOnSale
{
public:
StationTile();
~StationTile();
int getRent() override;
};
EDIT: added a potentially clarifying comment to code.
You might want to take a look at the visitor pattern.
In essence, the visitor allows one to add new virtual functions to a family of classes without modifying the classes themselves; instead, one creates a visitor class that implements all of the appropriate specializations of the virtual function. The visitor takes the instance reference as input, and implements the goal through double dispatch.
The double dispatch means you are actually calling a virtual function twice: first on the subject which in turn polymorphically calls the visitor.
In your case there is just one method, namely building houses, but you might want to add others later (like drawing them on a screen for example). Given your current example you should add this method to Tile and StreetTile:
virtual void accept(Visitor& v) { v.visit(*this); }
This is the Visitor base class implementation:
class Visitor {
public:
virtual void accept(Tile& t) = 0;
virtual void accept(StreetTile& t) = 0;
};
After that you can implement a Builder class:
class Builder: public Visitor {
private:
int numberOfHouses;
public:
Builder(int n): numberOfHouses(n) {}
virtual void accept(Tile& t) {}
virtual void accept(StreetTile& t) {
t.buildHouses(numberOfHouses);
}
};
After that all you have to do is construct such a builder, and call it on every tile in your vector of tiles:
Builder b(10);
for (Tile tile : tiles) {
tile.accept(b);
}
A Simple way is to add a unique id (enum or string) to each type. The player class can ask for the type (defined in the base class) and cast to the derived class accordingly.
Since it needs to call a function on the derived (e.g. specialized) class it has the knowledge to perform the cast.
Having a type ID is also nice for debugging purposes.
in C++;
Is there a way of calling a function from a derived class through the base class
even when the function is not overridden? In other words, I'm using a base class in
order to have heterogeneous containers without boost; I want to call a member function
that is only specific to a derived class...
Example:
(I just made this code up so there's probably a syntax error but hopefully you get the gist)
class Vehicle
{
public:
virtual void do_vehicle_stuff();
// virtual void do_car_specific_stuff(); makes no sense here
}
class Car : public Vehicle
{
public:
void do_vehicle_stuff();
void do_car_specific_stuff();
}
Car a,b;
list<Vehicle> vehicle_list;
vehicle_list.push_back(a);
vehicle_list.push_back(b);
vehicle_list.front().do_car_specific_stuff();
error: 'Class Vehicle' has no member named 'do_car_specific_stuff()'
You are slicing your classes when you insert them into the list. In
C++ subtype polymorphism (the kind of polymorphism you are using) only
works through references or pointers but not values. When you insert
your carS into the list they are converted to VehicleS.
An example:
Car c;
std::vector<Vehicle> vs;
vs.push_back(c); // slicing happens
vs.front(); // not a car anymore, but just a vehicle,
// the Car-ness is lost through the copy operation
How do to it:
std::vector<std::unique_ptr<Vehicle>> vs;
vs.push_back(new Car());
vs.front(); // actually a Car
After you have resolved that fundamental flaw of your code, this might
help you:
Vehicle* vehiclep = new Car();
if(auto carp = dynamic_cast<Car*>(vehiclep)) {
carp->do_car_specific_stuff();
}
This is a rather costly operation and usually an indication of a
design smell, so you might want to rethink what you are doing.
Here's a more appropriate design:
struct Vehicle
{
virtual ~Vehicle() { }
void do_vehicle_stuff()
{
vehicle_impl();
}
private:
virtual void vehicle_impl() = 0;
};
struct Car : Vehicle
{
private:
virtual void vehicle_impl()
{
my_vehicle_stuff();
my_car_specific_stuff();
}
void my_vehicle_stuff() { /* what you had originally */ }
void my_car_specific_stuff() { /* car-only stuff */ }
};
std::list<std::unique_ptr<Vehicle>> vehicles;
vehicles.emplace_back(new Car);
vehicles.emplace_back(new Motorcycle);
vehicles.emplace_back(new Carriage);
I'm new to C++ and i'm having a hard time figuring out what's wrong with my virtual functions. So, here's what i have:
GEntity.h
class GEntity
{
public:
//...
virtual void tick(void);
virtual void render(void);
//...
};
GEntity.cpp
//...
void GEntity::tick(void){}
void GEntity::render(void){}
//...
GLiving.h
class GLiving : public GEntity
{
public:
//...
virtual void tick(void);
virtual void render(void);
//...
};
GLiving.cpp
//...
void GEntity::tick(void){}
void GEntity::render(void){}
//...
Then i have other classes that derive from GLiving (Player, Enemy) which implement their own versions of this two methods:
Player.h
class Player : public GLiving
{
public:
//...
void tick(void);
void render(void);
//...
};
Player.cpp
//...
void GEntity::tick(void)
{
//Here there's some actual code that updates the player
}
void GEntity::render(void)
{
//Here there's some actual code that renders the player
}
//...
Now, if i declare an object of class Player, and call the render/tick method, everything goes well, but i am in a situation in which i add my player to an arraylist (a struct i created) of GEntity, and then, when i get it back, i get it as a GEntity, and i need to call the render/tick methods without knowing it's derived class...
I've tried with the code above, but i get an access violation in the line where i call either the render or tick method, on the extracted GEntity...
...is what i want even possible to achieve?
(sorry if my english is not so good, but i'm italian)
If you have an array of GEntity then, each time you "add" a derived type, the equivalent of this happens:
GEntity g;
Player p;
g = p; // object slicing, you assigned a Player to a GEntity object.
g.render(); // GEntity::render() gets called
On the other hand, you can use a pointer to a base class to access a derived method:
GEntity* g;
Player p;
g = &p;
g->render(); // calls Player::render()
So a way to deal with polymorphism in containers is to have arrays/containers of (preferably smart) pointers to the base class. This example uses raw pointers for simplicity, but you should use smart pointers in real code:
std::vector<CEntity*> entities;
entities.push_back(new Player);
entities.push_back(new GLiving);
// some c++11
for ( auto e : entities) {
e->render();
}
In a Game class function I am allocating a Boundary class to the stack
void Game::loadContent()
{
Boundary b(this, body);
}
The boundary class has a pointer to the main Game class and a pointer to a rigid body. I'm not certain whether I should use a reference for each though? Some clarity here would be helpful for reasons explained later.
class Boundary : public DynamicEntity
{
public:
Boundary(Game *game, btRigidBody *body);
~Boundary(void);
// Override functions
virtual void draw(float dt);
virtual glm::vec3 getPosition();
virtual void update(float dt);
};
The DynamicEntity class assigns the body and handles the pointer deletion in its destructor.
class DynamicEntity : public Entity
{
public:
virtual ~DynamicEntity(void);
virtual void draw(float dt) = 0;
btRigidBody* getBody();
glm::vec3 getPosition() = 0;
virtual void update(float dt) = 0;
protected:
explicit DynamicEntity(Game *game, btRigidBody *body);
btRigidBody *m_body;
};
DynamicEntity.cpp Destructor
DynamicEntity::~DynamicEntity(void)
{
m_game->m_dynamicsWorld->removeRigidBody(m_body);
delete m_body;
}
The DynamicEntity derives from the base class of all game objects called Entity
Entity.h
class Entity
{
public:
// Make destructor virtual as this is a base class
virtual ~Entity(void);
virtual void draw(float dt) = 0;
int getID();
virtual glm::vec3 getPosition() = 0;
virtual void update(float dt) = 0;
protected:
explicit Entity(Game *game); // Abstract base constructor
Game *m_game;
int m_id; // Unique ID
};
I can't call delete on the Game class pointer in this class' destructor though which is why I am not sure whether passing as a pointer is the correct method (instead of a reference)?
Entity::~Entity(void)
{
// Derived class destructors are called first
delete m_game; // ERROR
}
The Entity class adds a pointer to itself which can be accessed via a list in the Game class (useful for iterating and calling Entity functions in the main Game class).
Entity::Entity(Game *game)
: m_game(game), // Initialise members
m_id(m_game->g_idGenerator->generateNewID()) // Generate unique ID
{
m_game->m_entities.push_back(std::shared_ptr<Entity>(this));
}
The main problem I am having is that once the Game::loadContent() method has finished the destructor is called for the Entity class. This ruins the *shared_ptr* stored in the list and errors occur when trying to call any of the virtual methods.
I would like the Boundary pointer to persist until I say delete. Is there any way of doing this without allocating the Boundary to the heap?
EDIT
In response to the suggestion for using const& Game
It would appear that I have to change my Entity header to the following
Entity.h
#pragma once
#include <glm\glm\glm.hpp>
#include "Game.h"
// Forward declarations
class Game;
class Entity
{
public:
// Make destructor virtual as this is a base class
virtual ~Entity(void);
// '= 0' means pure virtual function (like 'abstract' in C#)
// This means they do not have to be declared in the source file '.cpp'
virtual void draw(float dt) = 0;
int getID();
virtual glm::vec3 getPosition() = 0;
virtual void update(float dt) = 0;
protected:
explicit Entity(const Game &game); // Abstract base constructor
Game m_game;
int m_id; // Unique ID
};
Doesn't the Game m_game allocate an instance of the Game class to the stack? How should it be declared in the header if it to represent a reference?
EDIT 2
If I store a protected reference to the Game class in the base Entity class const Game &m_game I cannot seem to access a global member of the Game class g_wireShapeDrawer in derived classes.
class Game
{
public:
GL_WireShapeDrawer g_wireShapeDrawer;
Game(void);
~Game(void);
void init();
void draw(float dt);
void handleInput(float dt);
void loadContent();
void update(float dt);
};
For example I get the following error when trying to access a global member in the draw method of the derived Boundary class source
void Boundary::draw(float dt)
{
m_game.g_wireShapeDrawer.drawPlane(glm::vec3(0, 1, 0), 0.0f, glm::vec4(1, 1, 1, 1));
}
error C2662: 'GL_WireShapeDrawer::drawPlane' : cannot convert 'this' pointer from 'const GL_WireShapeDrawer' to 'GL_WireShapeDrawer &
Why is this?
The Game object should never be deleted from any Entity or derived class. It should be one of the last things to be deallocated before the application shuts down.
You should pass it to your Entity classes as a Game&. Why? Because you only have one instance of the Game, so there is no need to reset what it points to, and it always should be valid (since the game will exist before the Entity objects do).
Another option is to implement the Singleton Pattern in your Game class, and access it like this Game::GetInstance().m_dynamicsWorld->removeRigidBody(m_body);
As per your edit, you can create an Entity using the initializer list. This way you can store const members, like so:
class Entity
{
protected:
explicit Entity(Game &game) : m_game(game) {}
private:
Game& m_game;
}
Your design is flawed. You need to clearly state (through your design) who owns the pointer. If Entity owns the pointer then it should deallocate it in its destructor as you are doing (better yet; just wrap it in a std::unique_ptr). If it does not own the pointer then simply don't deallocate it.
You cannot have it both ways. You're using a shared_ptr, so that implies multiple "owners" and, once the last owner is done with it, the memory will be deallocated. Again, you needs to clearly design around who owns this memory.
Judging from your code, it seems like Entity does not really own the Game*. It needs it for implementation reasons, but should not be responsible for its deallocation.
on a side note, you are violating The Rule of Three.
I am having a problem with the following code, the overriden virtual functions are not executing. Not sure i'm doing wrong here probably a silly mistake. Anyway this is a game project and I have an array of objects which looks like this (the core::array is an irrlicht array, similar to the vector array)
core::array<GameObject> gameTargets;
This is the GameObject and Zombie definition
class GameObject {
protected:
scene::ISceneNode* node;
public:
int ID;
int hitpoints;
GameObject() {
...
};
void setNode(scene::ISceneNode* inode) {
...
}
virtual void shot(int dmg) {
... [BREAKPOINT HERE]
}
scene::ISceneNode* getNode() {
return node;
}
};
class Zombie : public GameObject {
public:
static const enum Animation {
ZOMBIE_WALK,
ZOMBIE_HURT,
ZOMBIE_DIE,
ZOMBIE_TWITCH,
ZOMBIE_ATTACK,
ZOMBIE_IDLE
};
//We only want to accepted animated mesh nodes for this object
Zombie(int hp, scene::IAnimatedMeshSceneNode* inode) {
...
}
//Override the shot function
void shot(int dmg) {
... [BREAKPOINT HERE]
}
//Animate the zombie
void setAnimation(Animation anim) {
...
}
};
The member functions of the derived classes is never called, I am creating the objects like this
Zombie target(hp, (scene::IAnimatedMeshSceneNode*)node);
and calling the virtual function like this
for(int i = 0; (u32)i<level->gameTargets.size(); i++) {
if(selectedNode == level->gameTargets[i].getNode()) {
level->gameTargets[i].shot(b->damage);
}
}
where b is a pointer to a bullet with a int variable damage and gameTargets contains GameObject
I suspect that you're experiencing slicing because the gameTargets array contains values. I can't tell for sure because I don't know how the core::array template works. See What is object slicing? for a discussion about what slicing is.
To fix this problem, store either raw pointers as in
core::array<GameObject *> gameTargets;
Or use some sort of reference-counted pointer like
core::array<std::shared_ptr<GameObject>> gameTargets; // only available in C++11
array<GameObject> is a container of objects, not a container of pointers. Every object you add to it will be a GameObject and not one of the derived classes (if you add a derived class object, then it'll be "sliced").
Without knowing exactly what your core::array does, I suspect what you really intended to create is an array of std::unique_ptr<GameObject> (smart pointers) along the lines of
core::array< std::unique_ptr<GameObject> > gameTargets;
std::unique_ptr<GameObject> my_zombie(new Zombie);
gameTargets.push_back( my_zombie );
a quick solution would be to make those parent functions as pure virtual functions, as in:
virtual void shot(int dmg) { } = 0;
// edit
and use array of pointer as suggested by Frerich Raabe