Arduino C++ Inheritance and function declaration problem - c++

class Entity {
public:
virtual void applyCollisionBehaviorTo(Entity &entity) { }
virtual void onCollision(Entity &entity) { }
};
class Ball : public Entity {
public:
void applyCollisionBehaviorTo(Entity entity) override {
}
void onCollision(Entity entity) override {
entity.applyCollisionBehaviorTo(this); // error: no matching function for call to 'Entity::applyCollisionBehaviorTo(Ball*)'
}
};
void setup() {
// put your setup code here, to run once:
}
void loop() {
// put your main code here, to run repeatedly:
}
I come from a C# background so I'm getting my head around C++ inheritance and polymorphism.

Your class Entity should be like this:
class Entity
{
public:
virtual void applyCollisionBehaviorTo(Entity &entity) = 0;
virtual void onCollision(Entity &collidingEntity) = 0;
};
You can't refere to object of Ball class inside Entity, in fact entities don't even know about the existence of balls.
OTOH balls "know" that they are entities

Related

How to use dynamic_cast efficiently?

There is an abstract class Entity, and other classes like Player and Enemy are inherit from it. When game detects a collision between the entities, the following method is called:
void handleCollision(Entity* ent1, Entity* ent2) {
if (dynamic_cast<Player*>(ent1) || dynamic_cast<Player*>(ent2) &&
dynamic_cast<Enemy*>(ent1) || dynamic_cast<Enemy*>(ent2)) {
//player <-> enemy collision
}
else if (dynamic_cast<Player*>(ent1) || dynamic_cast<Player*>(ent2) &&
dynamic_cast<Projectile*>(ent1) || dynamic_cast<Projectile*>(ent2)) {
//player <-> projectile collision
}
else if () {
//...
}
else if() {
//...
}
}
Each entity has unique behavior when colliding with another, which depends on the type of entity (Player, Enemy, etc), that's why I need to check every possible combination between entities as shown above. But I don't like the fact it creates a huge else if chain, where each entity is checked multiple times. Is there another way of doing it?
Trying to expand Ben Voigt's comment about multiple virtual dispatch, something along the lines of:
void handleCollision(Entity* ent1, Entity* ent2)
{
ent1->collide_with(ent2);
}
Where:
class Entity
{
public:
virtual void collide_with(Entity*) = 0; // Dispatcher
virtual void handle_collision_with(Entity*) {}
virtual void handle_collision_with(class Player*) {}
virtual void handle_collision_with(class Enemy*) {}
virtual void handle_collision_with(class Projectile*) {}
};
class Player : public Entity
{
public:
virtual void collide_with(Entity* other) override
{
other->handle_collision_with(this);
}
virtual void handle_collision_with(Entity* other) override
{
// Unhandled entity
}
virtual void handle_collision_with(Player* other) override
{
// Handle collision player-player
}
virtual void handle_collision_with(Projectile* projectile) override
{
// Handle collision player-projectile
}
};
class Enemy : public Entity
{
public:
virtual void collide_with(Entity* other) override
{
other->handle_collision_with(this);
}
virtual void handle_collision_with(Enemy* other) override
{
// Handle collision enemy-enemy
}
virtual void handle_collision_with(Player* player) override
{
// Handle collision enemy-player
}
virtual void handle_collision_with(Projectile* projectile) override
{
// Handle collision enemy-projectile
}
};
class Projectile : public Entity
{...}
source: a-polyglots-guide-to-multiple-dispatch
Use a virtual function defined in Entity class to uniquely identify the derived class whether Player or Enemy. This will be a good practice to avoid any runtime errors as well.
enum EntityType { Entity, Player, Enemy}
In the Entity class define a virtual function like this,
virtual EntityType getType (return Entity;)
and override the function in two classes accordingly.

Call a function inside an unknown class that extends a known class

As the title says I have the following "base" class that user can extend:
class BaseScene
{
private:
bool sceneloop = false;
public:
virtual void Start();
virtual void EventHandler(SDL_Event event);
virtual void Update();
virtual void Draw();
void _toggleLoopMode() { sceneloop = !sceneloop; }
bool _sceneloop() { return sceneloop; }
};
My problem is I can't know what name, the user, choose for his classes so how I can call a known method (like Start or EventHandler) from my main class inside an unknown class?
An example of a class that is unknown to me but well-known to the user can be:
class SomeFunnyRandomName : public BaseScene
{
public:
void Start();
void Eventhandler(SDL_Event event);
void Update();
void Draw();
};
So form the main class I need to call Start() inside "SomeFunnyRandomName" without:
SomeFunnyRandomName sfrn = new SomeFunnyRandomName();
If you can include the code it will be very helpful (but not required).
You take a reference or pointer to BaseScene, and call the methods on that. The caller passes an instance of their derived class.
class UsesScene {
BaseScene & scene;
public:
UsesScene(BaseScene & scene) : scene(scene) {}
void doStuff() { scene.Start(); scene.Update(); }
/*... etc*/
};
int main() {
SomeFunnyRandomName scene;
UsesScene usesScene(scene);
usesScene.doStuff();
}

Is there any way to call unknown methods of a template argument class?

I once implemented a state machine like this:
class Player
{
public:
int Run();
int Jump();
int Stop();
private:
class State
{
public:
virtual int Run() = 0;
virtual int Jump() = 0;
virtual int Stop() = 0;
};
class StandingState : public State
{
virtual int Run() { /*...*/ }
virtual int Jump() { /*...*/ }
virtual int Stop() { /*...*/ }
};
class RunningState : public State
{
virtual int Run() { /*...*/ }
virtual int Jump() { /*...*/ }
virtual int Stop() { /*...*/ }
};
// More states go here!
std::list<State*> states;
State* currentState;
};
int Player::Run()
{
int result = m_currentState->Run();
// do something with result
}
int Player::Jump()
{
int result = m_currentState->Jump();
// do something with result
}
int Player::Stop()
{
int result = m_currentState->Stop();
// do something with result
}
Fairly textbook I should think: Player delegates the calls from outside to its current State object, and does something with the result (possibly transitioning to another state). Essentially, each state knows how a given action affects it, but it's up to the state machine to wire the various states together. I found this to be a good separation of concerns.
But I'm seeing a possibility for abstraction here. The entire system is defined by the interface of the State class:
Both the state machine and the substates implement State
The state machine keeps a pointer to all possible States and the current State
Whatever method of State is called on the state machine, it is undiscerningly forwarded to the current state.
So, we can totally make this a class template, right? Look:
template< class StateInterface >
class StateMachine : public StateInterface
{
// public methods already declared in StateInterface
protected:
std::list<StateInterface*> states;
void AddState(StateInterface* state);
StateInterface* currentState;
};
class PlayerStateInterface
{
public:
virtual int Run() = 0;
virtual int Jump() = 0;
virtual int Stop() = 0;
};
class Player : public StateMachine< PlayerStateInterface >
{
public:
virtual int Run() { currentState->Run(); /* do stuff */ }
virtual int Jump() { currentState->Jump(); /* do stuff */ }
virtual int Stop() { currentState->Stop(); /* do stuff */ }
};
Of the above points, this has 1 and 2 covered, but what about 3? I still have to manually delegate the calls to the current state in the concrete state machine implementation. Is there a way to move that functionality to the StateMachine template? Can I somehow express that whenever a method of StateInterface is called on StateMachine it should call the same method on currentState, when I don't know the names or signatures of StateInterface's methods?
If you're looking for a general answer to the case where Run, Jump, and Stop have different signatures, I don't know if there's a good solution. However, in your example they all have the same signature, which suggests to me that the following approach might work:
#include <iostream>
class AbstractState
{
public:
virtual void write1() = 0;
virtual void write2() = 0;
};
class State1: public AbstractState
{
public:
virtual void write1() { std::cout << "1-1" << std::endl; }
virtual void write2() { std::cout << "1-2" << std::endl; }
};
class State2: public AbstractState
{
public:
virtual void write1() { std::cout << "2-1" << std::endl; }
virtual void write2() { std::cout << "2-2" << std::endl; }
};
template <typename StateInterface>
class Player
{
public:
Player(StateInterface *s_):
s(s_)
{
}
void setState(StateInterface *s_)
{
s = s_;
}
void execute(void (StateInterface::*method)())
{
(s->*method)();
}
private:
StateInterface *s;
};
int main()
{
State1 s1;
State2 s2;
Player<AbstractState> p(&s1);
p.execute(&AbstractState::write1);
p.execute(&AbstractState::write2);
p.setState(&s2);
p.execute(&AbstractState::write1);
p.execute(&AbstractState::write2);
return 0;
}
I was able to compile and run this with GCC 4.5.2 and got the expected result, namely:
1-1
1-2
2-1
2-2
As I said, I'm not sure that there's a good way to extend this to the case where the different member functions of AbstractState take different parameters or return different values, and there may be other drawbacks that I haven't considered yet. It isn't quite as nice as what I think you were hoping to find, but hopefully this will at least serve as a good starting point.

C++ Keeping a reference /pointer of an abstract type

I'm new to c++ and this question probably seems noobish as I'm just more of a Java/Actionscript3 and I've never dealt with memory related things before.
Anyhow as for the problem I have:
Scene is an abstract class (so I can derive from it and have multiple scenes, like MainScene etc')
What I wanted SceneManager to do is have a pointer / reference to the selected scene (curSc)
And then I'd set the scene like so: setScene(&someScene)
But as I understand, to have a pointer I must also initialize it like so:
curSc = new Scene;
But it won't let me do that as Scene is an abstract class..
class Scene {
public:
Scene(void){}
virtual ~Scene(void){}
virtual void update() = 0;
virtual void render() = 0;
};
class SceneManager {
public:
SceneManager(void);
~SceneManager(void);
void setScene(Scene *sc);
Scene* curSc;
}
So far it seems to me like using a pointer in this case is wrong and it won't work..
But I'd love to know how to achieve the functionality I'm trying to obtain here
Thank you very much
Edit by request:
that's how I tried to use it:
Firstly I have a derived class named GameScene and here it is:
class GameScene : public Scene
{
public:
GameScene(void);
void render();
void update();
}
in my main() function I have:
GameScene gamescene;
ScreenManager manager;
manager.setScene(&gamescene);
you need a concrete derived class of Scene:
class MyScene: public Scene {
public:
MyScene(void){}
virtual ~MyScene(void){}
virtual void update();
virtual void render();
};
And void setScene(Scene *sc) will be:
void setScene(Scene *sc)
{
curSc = (Scene*)sc;
}
sc will be MyScene pointer in this case. Abstract class instances (ie interfaces) can not be created and Scene is just an interface here.
Exactly. You can not do
curSc = new Scene
because it is abstract. If you actually want to declare an instance of Scene then make it non abstract. i.e. implement all the methods.
OR (I think this is what you intended to do) create a class that inherits from Scene and implements all the virtual methods.
class View : public Scene {
public:
View(){}
virtual ~View(void){}
virtual void update();
virtual void render();
};
and implement the virtual methods like
void View::update() {
//
}
void View::render() {
//
}
Then you can implement setScene as
void SceneManager::setScene(Scene *sc)
{
curSc = sc;
}
and call it like
SceneManager smag;
Scene *nsc = new View;
smag.setScene(nsc);
It is not wrong to use pointer here. But unlike a reference, a pointer urges its user to account for NULL. That is the caveat. Reference can refer to NULL as well, but adding defense against it will lead you to the "dark side". So, it is reasonable to assume reference will refer to alive object and in this sense references are better than pointers.
Now, if you really-really want to keep the reference you can use in-place construction technique, because you can (re)assign reference by constructor:
class SceneManager {
public:
SceneManager(Scene& sc) : curSc(sc) {}
~SceneManager(void);
SceneManager& setScene(Scene &sc) {
SceneManager* cheatCompiler = new(this) SceneManager(sc);
return *cheatCompiler;
}
Scene& curSc;
}
Note, that this is kind of quirky stuff. Since compilers try to outsmart us all the time, I can not guarantee it will work in all cases.
That said I would still recommend you using the pointer. If you dont want to check for NULL all the time, you can implement something like Null Object Pattern.
You should use smart pointers, and do not make member variables public. Example:
class Scene {
public:
virtual ~Scene(){}
virtual void update() = 0;
virtual void render() = 0;
};
class MyScene : public Scene {
public:
virtual void update () { /*...*/ }
virtual void render () { /*...*/ }
};
class SceneManager {
public:
SceneManager();
~SceneManager();
void setScene(const std::shared_ptr<Scene> & sc) {
curSc = sc;
}
private:
std::shared_ptr<Scene> curSc;
};
void someProc () {
std::shared_ptr<Scene> sc = std::make_shared<MyScene> ();
auto manager = std::make_shared<SceneManager> ();
manager->setScene (sc);
// ...
}
Without smart pointers, this would look like (but remember to delete the objects created with new if they are not needed anymore):
class Scene {
public:
virtual ~Scene(){}
virtual void update() = 0;
virtual void render() = 0;
};
class MyScene : public Scene {
public:
virtual void update () { /*...*/ }
virtual void render () { /*...*/ }
};
class SceneManager {
public:
SceneManager();
~SceneManager();
void setScene(Scene * sc) {
curSc = sc;
}
private:
Scene * curSc;
};
void someProc () {
Scene * sc = new MyScene;
SceneManager * manager = new SceneManager;
manager->setScene (sc);
// ...
}

Is this template visitor really dynamic?

I have been playing around with various methods of making the Visitor pattern in C++ more dynamic, such that sibling classes don't have to know about each other, and that allows later extension of the visitor hierarchy. I came up with this example based on "More Effective C++" by Scott Meyers:
class Dummy
{
public:
void collide(int& gameobject) { }
};
class DynVisitor
{
public:
template<class Visitor=Dummy, class Arg=int>
void visit(Arg& target)
{
Visitor* vis = dynamic_cast<Visitor*>(this);
if(vis != nullptr)
{
vis->collide(target);
}
else
{
cerr<<"No implementation!"<<endl;
}
}
virtual ~DynVisitor() { }
};
class GameObject
{
public:
virtual ~GameObject() { }
virtual void collide(GameObject& obj)
{
cout<<"Default collide implementation"<<endl;
}
virtual void accept(DynVisitor* vis) = 0;
};
class AsteroidVisitor
{
public:
virtual void collide(Asteroid& target) = 0;
virtual ~AsteroidVisitor() = 0;
};
class Collider : public DynVisitor, public AsteroidVisitor
{
public:
virtual void collide(Satellite& target) { cout<<"Satellite collision."<<endl; }
virtual void collide(Spaceship& target) { cout<<"Spaceship collision."<<endl; }
virtual void collide(Asteroid& target) { cout<<"Asteroid collision."<<endl; }
virtual ~Collider() { }
};
class Asteroid : public GameObject
{
public:
virtual void accept(DynVisitor* visitor)
{
visitor->visit<AsteroidVisitor, Asteroid>(*this);
}
};
int main(int argc, char** argv)
{
DynVisitor* coll = new Collider();
GameObject* ast = new Asteroid();
ast->accept(coll);
delete ast;
delete coll;
return 0;
};
This appears to work as I would expect, printing out "Asteroid collision" when the GameObject passed is an Asteroid, and I can add classes to the hierarchy just by defining a new ABC with a collide() method and extending DynVisitor.
My question is, when I add a new class to the hierarchy, does DynVisitor need to be recompiled?
EDIT: Added the asteroid class... sorry about that.
All objects can collide with each other, so they still need to be visitors of each other and hence there is no added "dynamism". DynVisitor is a template and thus needs to be in the translation unit and will be recompiled everytime. In fact, in this example, DynVisitor does't give any benefit because the accept() function can call the collide() function instead of the template visit() function.