How to properly use virtual member functions in c++ - c++

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

Related

Whether using dynamic cast for providing input for derived class virtual function is recommended?

I read some of the answers in What is the proper use case for dynamic_cast.
The line which best matched my situation here is
#include<iostream>
class Shape
{
public:
virtual void draw()=0;
virtual ~Shape(){};
};
class Rectangle : public Shape
{
public:
int length;
int breath;
void draw()
{
std::cout<<"RECTANGE"<<std::endl;
}
};
class Circle : public Shape
{
public:
int diameter;
void draw()
{
std::cout<<"CIRCLE"<<std::endl;
}
};
/*Abstract Factory*/
Shape* getShapeObj(int type)
{
switch(type)
{
case 1:
return new Rectangle;
case 2:
return new Circle;
/* many types will be added here in future. */
}
return NULL;
};
void drawShapes(Shape *p_shape[],int len)
{
for(int i=0;i<len;i++)
p_shape[i]->draw();
}
int main()
{
Shape *l_shape[2];
l_shape[0]=getShapeObj(1);
l_shape[1]=getShapeObj(2);
Rectangle *l_rec=dynamic_cast<Rectangle*>(l_shape[0]);
if(l_rec)
{
l_rec->length=10;
l_rec->breath=20;
}
Circle *l_circle=dynamic_cast<Circle*>(l_shape[1]);
if(l_circle)
l_circle->diameter=25;
drawShapes(l_shape,2);
}
Essentially, virtual functions only work in some cases, not all of them.
My problem is to pass the input for the virtual function and inputs will vary from type to type. Whether using dynamic cast is recommended here?
The solution is perfect forwarding of function parameters, introduced in c++11.
template<typename ...CtorArgs>
Shape* getShapeObj(int type, CtorArgs&& ctor_args...)
{
switch(type)
{
case 1:
return new Rectangle(std::forward<CtorArgs>(ctor_args)...);
// many types will be added here in future.
}
return NULL;
}
Obviously making the function a template, defeats the purpose of hiding the hierarchy (as well as forcing rather strict requirements on the number of parameters to the constructors). But if the base contains a map of functions that do the construction, which each derived class updates with a pointer to function that constructs it, you can still have information hiding.
I have recently written an answer about storing type erased function pointers in a map, with some static type checking forwarded to run time.
In this particular case, looks like your main function is taking too much responsibility. What if you have Circle, Hexagon, MyFancyFigure types? All of them should be initialized in main in different branches?
It would be much better to move that "initialization" logic to a separate virtual function init in your classes (or even to the constructor). The code would look like this:
class Shape
{
public:
virtual void draw()=0;
virtual void init()=0;
virtual ~Shape(){};
};
class Rectangle : public Shape
{
public:
int length;
int breath;
void draw()
{
//Draw Rectangle
}
void init()
{
length = 10;
breath = 20;
}
};
int main()
{
Shape *l_shape=getShapeObj(1);
// Calls different code of "init" method depending on the actual object type
l_shape->init();
l_shape->draw();
delete l_shape;
}
Also, please note that this initialization logic may be place in some other place, like constructor of the class or the factory method. But main is definitely the wrong place.

C++ command pattern

I'm trying to implement something like a command pattern to control serveral components with the same interface. Every component must implement the following interface.
class ComponentInterface {
public:
virtual int start() = 0;
virtual int stop() = 0;
};
Every derived component will implement some specific methods.
class Led : public ComponentInterface {
public:
/**
* Implements Interface methods
*/
int start() { return 0; }
int stop() { return 0; }
private:
int setIntensity(int attrs[], int returns[]) {
printf( "Set intensity called" );
return 1;
}
};
The main idea is that every subclass store the callable member functions in an array of pointers and in the ComponentInterface class will be implemented a methods that can call this functions based on the index of the command.
class ComponentInterface {
public:
...
// for storing the pointers
int (ComponentInterface::*commandsArray[10])(int[], int[]);
// to call the member functions
int command(int commandId, int attrsList[], int responseList[]) {
return (this->*commandsArray[commandId])(attrsList, responseList);
}
}
class Led : public ComponentInterface {
public:
Led(float* ledIntensity) {
// store the command in the array
this->commandsArray[0] = (&Led::setIntensity);
}
// redefine the array for pointers of this subclass
int (Led::*commandsArray[5])(int[], int[]);
};
I'm not familiar with C++ and I don't understand why it doesn't work, I have problems when calling the stored functions.
When testing with devC++, I get a segmentation fault. When i tried to test it in Visual Studio 2013 (Visual C++) and with the debugger it seems that in this row
(this->*commandsArray[commandId])(attrsList, responseList);
, the this object is pointing to the ComponentInterface object instead of the Led object.
Two things are immediately wrong in your code:
You can't "override a base class variable" and this line doesn't quite make sense in your derived class
// redefine the array for pointers of this subclass
int (Led::*commandsArray[5])(int[], int[]);
This cast is wrong
this->commandsArray[0] = (&Led::setIntensity);
it should rather be
this->commandsArray[0] = static_cast<int (ComponentInterface::*)(int*,int*)>(&Led::setIntensity);
Anyway a cleaner and safer way to achieve what you want is the following:
(Disclaimer: heavy stripping ahead, ignoring everything that doesn't immediately matter in the discussion)
class ComponentInterface {
..
std::vector<std::function<int (int[], int[])>> commandsArray;
}
Live Example
You could then store member functions with different signatures (bound to the right object) and just use the ComponentInterface container in your components.

Component based architecture c++

I'm having trouble figuring out a way to make a component based engine architecture in c++. But i cant figure out a way to combine a vector of components with a class that derives from component.
I want to override components virtual function. But the only way i can make it call the overrided function is to make the component-derived class a pointer, but i want every gameobject to contain its own components in a vector and not outside the class as a pointer.
I tried to remove as much unnecessary code as possible.
My structure:
//GameObject class, contains components and other objects
class GameObject
{
public:
GameObject(){}
~GameObject(){}
void AddChild(GameObject child)
{
children.push_back(child);
}
void AddComponent(Component component)
{
components.push_back(component);
}
void Input(){}
void Update(){}
void Render()
{
for(unsigned int i = 0; i < components.size(); i++)
components[i].Render();
}
private:
std::vector<GameObject> children;
std::vector<Component> components;
};
//base class component
class Component
{
public:
Component(){}
~Component(){}
virtual void Input(){}
virtual void Update(){}
virtual void Render(){ cout << "Component -> Render()" << endl; }
};
class MeshRenderer : public Component
{
public:
MeshRenderer(Mesh _mesh, Material _material)
{
mesh = _mesh;
material = _material
}
~MeshRenderer(){}
//override components virtual Render()
void Render(Transform transform)
{
mesh.Render(material);
cout << "MeshRenderer -> Render()" << endl;
}
private:
Mesh mesh;
Material material;
};
GameObject* root = new GameObject();
MeshRenderer meshRenderer(mesh, material);
root->AddComponent(meshRenderer);
//GameLoop
while(!quit)
{
root->Render();
}
It would be the best if you could use unique_ptr:
void AddComponent(std::unique_ptr<Component> component) {
components.push_back(std::move(component));
}
std::vector<std::unique_ptr<Component>> components;
Thus by calling AddComponent() you transfer ownership of the component to containing GameObject.
Looks like you want to pass your objects by reference, use
void AddComponent(Component& component);
to avoid any slicing.
For proper usage with std::vector<>'s and polymorphic inheritance, you'll need smart pointers, e.g. std::unique_ptr<Component> to preserve ownership, or std::shared_ptr<Component> for shared ownership (raw pointers as Component* might work as well, but are far harder to manage correctly).
void AddComponent(std::unique_ptr<Component> componentPtr); // Unique ownership
or
void AddComponent(std::shared_ptr<Component> componentPtr); // Shared ownership
and accordingly
std::vector<std::unique_ptr<Component>> components;
or
std::vector<std::shared_ptr<Component>> components;
It depends on your actual use cases if these Component instances should be uniquely owned by their aggregating parent GameObject class, or not.
To use std::shared<> pointers, that could expire outside their usages scope you may consider using std::weak_ptr<>.
As mentioned, it totally depends on your use cases, and how you want these aggregated components being accessible from outside of the GameObject class.

Calling virtual method from base class C++

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();
}

Workaround for Interface

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
}