C++ Disallowing certain functions if object is of a type - c++

I've got a weird quality of life problem:
Entity* Bob = new Camera where Entity (abstract) is a type of object that I want in an vector array. And Camera is the specific object.
I have no problems with getting Camera to inherit and implement the functions of Entity into camera. the Camera runs fine. The problem arises when I create another object with Entity* Joe = new Cube;
Now I want to be able to group together Joe and Bob, but Bob, being a moving object, I want him to inherit the ProcessKeyboard(); function, so I can use it when using Bob. But Joe doesn't move, so I'd rather Joe not even have access to the ProcessKeyboard(); function.
Now, I could make Joe's ProcessKeyboard function do nothing, but I'd rather the compiler not allow me to to present it as an option for Joe to do.
I think my main question is what should I be looking up to solve this?

I believe the most logical solution would be:
class Entity
{
virtual void Update() = 0;
}
class Camera : public Entity
{
void Update() override {
// ...
}
void ProcessKeyboard() {
// ...
}
}
class Cube : public Entity
{
void Update() override {
// ...
}
}
Then you store entities and cameras separately:
vector<Entity*> entities; // pointers to all your entities are here
vector<Camera*> cameras; // additionally track Camera objects
for(auto entity : entities) {
entity->Update();
}
for(auto camera : cameras) {
camera->ProcessKeyboard();
}
...I want him to inherit the ProcessKeyboard(); function, so I can use
it when using Bob.
As you see, in order to use ProcessKeyboard() you don't need to inherit it; Also I must say, that because ProcessKeyboard() is not virtual there are no additional vtables involved (only for Entity) and no vtable lookup occur on ProcessKeyboard() call. And it is good.
However, if there are a lot of different "movable" objects and you don't care about performance so much... The OOP-style solution is obvious: just create an "interface" for movable objects.
class IMovable
{
virtual void ProcessKeyboard() = 0;
}
class Camera : public Entity, public IMovable
{
void Update() override {
// ...
}
void ProcessKeyboard() override {
// ...
}
}
Usage:
vector<Entity*> entities; // the same approach
vector<IMovable*> movable; // additionally track all movable objects
for(auto entity : entities) {
entity->Update();
}
for(auto object : movable) {
object ->ProcessKeyboard();
}
Besides of everything was said, there is also a dynamic_cast but in this particular case, it sounds like last-minute decision making...

Related

Using funcion overload with the different child classes when I only have a list that contains the parent class

First a little explanation of my code to put into context the problem:
I have a class that is responsible for drawing stuff on the screen, I use an overloaded function to draw the different types of drawable entities, the fuctions look like this:
draw(entityType1* name);
draw(entityType2* name);
draw(entityType3* name);
...
All entities classes are derived from a parent "Entity" Class
I wrote a class named "Scene" that has an entity list with all drawable objects in the scene, I'm passing that scene object to the class responsible for drawing stuff on the screen.
The idea is to go through the list and to use function overload to draw the different type of objects on the list, but since the list only contains objects of the type Entity I can't really use the function overload since it only works with the child classes
I'm looking for a code similar to this one
void Painter::draw(Scene* scene) {
std::list<Entity*> drawables = scene->getDrawables();
for (auto it = drawables.begin(); it != drawables.end(); it++) {
draw(*it); //Should apply the correct overload
}
}
This code obviously doesn't work since I dont have any draw() function that takes an entity type.
I could always ask for the entity type to do a case to case, but that defeats the purpose of having an overloaded function and breaks the "tell, don't ask" principle.
I'm probably doing something terribly wrong, but I don't really know how to proceed that's why I'm asking the question, I would like to know what's the right approach to solve this problem while respecting the OOP principles, posibilities are wide open, everything is on the table in terms of changing my code.
Thanks in advance
You can use the Visitor pattern to solve this problem. This pattern is delegating the function call to the object itself, so you don't need to use the type of the object to call the correct function.
Here is how you can implement it:
void Painter::draw(Scene* scene) {
std::list<Entity*> drawables = scene->getDrawables();
for (auto it = drawables.begin(); it != drawables.end(); it++) {
(*it)->accept(this); // call virtual function
}
}
// in Entity class
void Entity::accept(Painter* painter) {
painter->draw(this);
}
// in entityType1 class
void entityType1::accept(Painter* painter) {
painter->draw(this);
}
// etc...
More advanced implementation of the visitor pattern can be found here: Implementing the visitor pattern using C++ Templates
If I'm understanding your question correctly, what you wanted is to have the logic of draw in the Painter class, while the original Entity types remain unchanged. You can achieve this through type erasure:
struct DrawableEntityView
{
template<std::derived_from<Entity> EntityType>
DrawableEntityView(const EntityType& entity)
: p_entity(&entity)
, drawn_by_impl{
[](const Entity* entity, const Painter& painter) {
painter.draw(static_cast<const EntityType*>(entity));
}
}
{}
void drawn_by(const Painter& painter) const
{ drawn_by_impl(p_entity, painter); }
private:
const Entity* p_entity;
void (*drawn_by_impl)(const Entity*, const Painter&);
};
What this essentially does is DrawableEntityView can be constructed with any derived class of Entity. When you construct a DrawableEntityView like:
EntityType1 e1;
DrawableEntityView e1_view{e1};
This will store an Entity* in e1_view, and the function pointer drawn_by_impl will store a lambda that can cast the p_entity to the type based on what it was constructed with, and call Painter::draw with it.
Now you can have some code like:
EntityType1 e1;
EntityType2 e2;
EntityType3 e3;
std::vector<DrawableEntityView> vec{e1, e2, e3};
Painter painter;
for(auto& entity: vec)
{
entity.drawn_by(painter);
}
And of course, you can simply add a member function in Painter like:
void Painter::draw(const DrawableEntityView& entity) const
{ entity.drawn_by(*this); }
Now in the for loop, you can have:
for(auto& entity: vec)
{
painter.draw(entity);
}
Here's a demo: https://godbolt.org/z/fPM4nv3xz
I made this a view purposely, but you can also made DrawableEntity::p_entity an owning pointer, and remove some of the const. Now you can have the scene store the entities as DrawableEntity directly.

Best way to store all entities in C++ game

I'm trying to create a way to hold all entities in my C++ game, arrays wouldn't work since they are limited to one type. I need to store anything with the class Entity, and all it's derivatives in it. I've been trying all day to get a way to store all game entities in a way I can just loop through them all and draw them. Still haven't found a solution.
Assuming Entity is some base class that many things derive from, you can have a container (any container is fine, but std::vector is a good place to start unless you have some other specific requirements).
class Entity
{
public:
virtual void Draw() = 0;
};
class Atom : public Entity
{
public:
void Draw() override {}
};
class Environment : public Entity
{
public:
void Draw() override {}
};
int main()
{
std::vector< std::shared_ptr<Entity> > entities;
entities.push_back(std::make_shared<Atom>());
entities.push_back(std::make_shared<Environment>());
// Draw entities:
for (size_t ent = 0; ent < entities.size(); ++ent)
{
entities[ent]->Draw();
}
return 0;
}
You might be able to use std::vector. It has a lot of built-in functions for simple data manipulation, and you can use it with any type.

How to "skip" certain child class functions

I wasn't sure how to exactly title this, but I am trying to figure out something with polymorphism.
So basically, I want to have an array of the parent class (object) that holds a bunch of it's child classes (ones that are and aren't collidable). However, I want to be able to put this array into a loop and run the collision function for only the collidable child class, but since the other child class doesn't have a collide function, how can I do this?
(Looks something like this)
class Object
{
protected:
Image image; // Pseudo code to make point
public:
void Collision() = 0;
//Constructor/Destructor
Object(void);
~Object(void);
};
class Collidable : Object
{
private:
Position myPosition; // Pseudo code to make point
public:
void Collision(); // Has collision function for parent class
//Constructor/Destructor
Collidable(void);
~Collidable(void);
};
class Uncollidable : Object
{
private:
Position myPosition; // Pseudo code to make point
public:
// No collision function for parent class
//Constructor/Destructor
Uncollidable(void);
~Uncollidable(void);
};
int main()
{
Collidable collide1, collide2, collide3;
Uncollidable uncollide1, uncollide2, uncollide3;
Object *objects[] { collide1, collide2, uncollide1, uncollide2, uncollide3, collide3 };
for(int i = 0; i < 6; i++)
{
objects[i].Collide(); // Should not work.
}
return 0;
}
^(this was just an example to help show my question, do pardon some of the syntax errors if any)
I'm pretty sure, however, that something like this would be an error since void Collide() doesn't exist in the Uncollidable class. So how might I be able to still run the void Collide() function in the loop while avoiding error? Or is something like this impossible and I just have to make two separate arrays?
I hope I explained my question well.
(I tried to research this, but every time I tried I just got sent to the basics of polymorphism)
You can just do this:
for(int i = 0; i < 6; i++)
{
Collidable c = dynamic_cast<Collidable*>(objects[i]);
if(c != nullptr) // dynamic_cast will return null if objects[i] is not of type Collidable
c->Collide(); // Should work.
}
In your code there is one bug, you have made Collide() pure virtual in class Object, but you are not overriding it in Uncollidable. It will not work. Either override it in Uncollidable (which is inappropriate), or give a default body to Object::Collide() (which is inappropriate also).
There is a better design, put all the common interface in Object, separate out different behaviors in other interface. It will lead to good OO design ( compliant with IS-A relationship)
class Object
{
protected:
Image image; // Pseudo code to make point
public:
Object(void);
~Object(void);
//other common interface
};
class Collidable // this is an interface that represent 'collidable' behavior
{
public:
virtual void Collision() = 0;
}
class CollidableObject : public Object, public Collidable
{ ... }
class UncollidableObject : public Object
{ ... }
Note: Object must be inherited publicly, otherwise you will not be able to treat object os CollidableObject and UncollidableObject as object of Object.

Keeping track of objects created by other objects?

Let's say I have a list of objects, objA. Now objA can create more objA, and they will be completely unrelated to one another - they do not care to know about other objA existence in the slightest. How could I get the objA created by another objA without storing objA inside of it's spawner? I don't want to use a singleton to represent the list of objA.
Example:
class Container
{
list<Monster*> listOfMonsters;
void UpdateAllMonsters()
{
foreach(Monster monster in listOfMonsters)
{
monster.Update();
}
}
};
class Monster
{
void Update()
{
new Monster();
}
};
How could I get the Monster created in the Update() method and stick it in the Containers listOfMonsters? I only want one instance of the Container object floating around, and the monsters shouldn't be able to do anything with the container object.
One solution I have thought of is creating an intermediate object between the Container and the Monster, so that there would only be one instance of the Container object, and the monster could essentially only access one method of the Container object(which would be adding to the listOfMonsters).
IE;
class Container
{
list<Monster*> listOfMonsters;
void UpdateAllMonsters()
{
foreach(Monster monster in listOfMonsters)
{
monster.Update();
}
}
void AddToList(Monster* monster)
{
listOfMonsters.add(monster);
}
};
class ContainerLiason
{
private __Container*;
AddToContainer(Monster* monster)
{
__Container.AddToList(monster);
}
};
class Monster
{
private ContainerLiason* __liason;
void Update()
{
__liason.AddToContainer(new Monster());
}
};
Are there any other ideas or design patterns?
One other thing, would the above example be a type of design pattern and what would it be called if so? I just ask because I've used singletons before I knew what they were called or even what they were.
The factory pattern should do what you need. Let the container (aka the factory) not only hold the list of created objects but also take care of the object creation itself:
class Factory {
list<shared_ptr<Monster>> listOfMonsters;
public:
void UpdateAllMonsters() {
for(auto pMonster : listOfMonsters) {
monster->Update();
}
}
shared_ptr<Monster> createMonster() {
auto newMonster = make_shared<Monster>();
listOfMonsters.push_back(newMonster);
return newMonster;
}
};
class Monster {
shared_ptr<Factory> theFactory;
public:
void Update() {
auto newMonster = theFactory->createMonster();
// ...
}
};
Note also that you asked under the C++ tag - your code does not really look like it
Your solution seems to be the one, you just need to be sure that all monster have the same pointer on ContainerLiaison, you can use a reference if you want.
Another solution is to have a reference on the Containter in each monster, but I think your ContainerLiason is better.
A last solution is static element and function, but I don't like it.
I suggest that you keep your solution
Okay, so you definitely do not need to use a singleton here. The simplest option is simply to Update a reference to a MonsterContainer as a parameter.
class Container
{
using MonsterList = list<Monster*>; // you should use a shared container or shared_ptrs here instead I think.
MonsterList listOfMonsters;
void UpdateAllMonsters()
{
foreach(Monster monster in listOfMonsters)
{
monster.Update(listOfMonsters);
}
}
};
class Monster
{
// You should change the name of your function here. Update does not imply
// creation to me. I would call it "CreateMonsterInList"
void Update(MonsterList& monsterContainer)
{
monsterContainer.add( new Monster() );
}
}

Converting objects of base class to derived class

I asked a couple days ago some clarifications on inheritance, a concept I am still trying to understand. Here is the follow up question, since I am still facing problems.
In my project I have 2 types of objects, Hand and Face, both inheriting from the base class BodyPart. BodyPart is something like this:
class BodyPart
{
public:
typedef boost::shared_ptr<BodyPart> BodyPartPtr;
BodyPart();
virtual ~BodyPart();
private:
int commonMember1;
double commonMember2;
public:
int commonMethod1();
int CommonMethod2();
}
while Hand is something like this:
class Hand : public BodyPart
{
public:
Hand();
~Hand();
private:
int numFingers;
double otherVar;
public:
int getNumFingers();
void printInfo();
}
I also have a vector of BodyPart elements
std::vector<BodyPart::BodyPartPtr> cBodyParts;
composed of Hand or Head objects. In the previous question I was told that this approach makes sense, I just had to cast from the base class to the derived using boost static_pointer_cast
Now, the problem now is that for some of the objects in the vector I don't know whether they are Hand or Head, so at some point in my code I can have in cBodyParts some Hand elements, some Head elements as well as some BodyPart elements. After some further analysis I am able to correctly classify the latter as either Hand or Head and modify accordingly the elements in the vector, but I have no idea on how to make it. Shall I just delete the case class element and create a derived one with the same property? Shall I just avoid inheritance in case like this?
Thanks in advance for the help
EDIT: I have augmented the examples to make them clearer.
Relaying on casts is usually a sign of a bad design. Casts have their place, but this does not look to be it.
You need to ask yourself what do you want to do with the objects stored in cBodyParts. For sure, you will be doing different things with a Hand or with a Head, but you can probably abstract them somehow: this is what virtual functions do. So, in addition to what you have already written for your classes, you would just need an additional virtual function in them:
class BodyPart
{
// Same as you wrote, plus:
public:
virtual void InitialisePart() = 0; // Pure virtual: each body part must say how to process itself
virtual void CalibrateJoints() {} // Override it only if the body part includes joints
}
class Head : public BodyPart
{
// Same as you wrote, plus:
public:
virtual void InitialisePart() {
// Code to initialise a Head
}
// Since a Head has no joints, we don't override the CalibrateJoints() method
}
class Hand : public BodyPart
{
// Same as you wrote, plus:
public:
virtual void InitialisePart() {
// Code to initialise a Hand
}
virtual void CalibrateJoints() {
// Code to calibrate the knuckles in the hand
}
}
And then you no longer need any casts. For instance:
for (BodyPart::BodyPartPtr part : cBodyParts) {
part->InitialisePart();
part->CalibrateJoints(); // This will do nothing for Heads
}
As you can see, no casts at all and everything will work fine. This scheme is extensible; if you later decide that you need additional classes inheriting from BodyPart, just write them and your old code will work correctly:
class Torso : public BodyPart
{
public:
virtual void InitialisePart() {
// Code to initialise a Torso
}
// The Torso has no joints, so no override here for CalibrateJoints()
// Add everything else the class needs
}
class Leg : public BodyPart
{
public:
virtual void InitialisePart() {
// Code to initialise a Leg
}
virtual void CalibrateJoints() {
// Code to calibrate the knee
}
// Add everything else the class needs
}
Now you don't need to change the code you wrote previously: the for loop above will work correctly with and Torso or Leg it finds with no need for an update.
The hip bone's connected to the thigh bone...
I take it you have some composite of all the body parts, maybe a Body class.
What do you want the body to do?
Render itself
Serialise
Ouput its volume, or bounding box, or some other metric
Re-orient itself in response to input
Respond to an inverse-kinematic physical model
The list could probably go on. If you know exactly what you want the Body to do you can put that function in the BodyPart base class, and have Body iterate over the composite hierarchical structure of all the connected body parts, calling render, for example.
An alternative is to use a Visitor, which is effectively a way of dynamically adding methods to a static inheritance hierarchy.
As Kerrek SB pointed out this is not feasible at all, but for the sake of answering the actual question, dynamic_cast is what you are looking for.
Use virtual functions, they will simplify a lot your problem.
Else, you can add some methods to distinguish between different types. However, do it only if you cannot do it another way, ie if you cannot do it via virtual functions.
Example 1:
// in BodyPart; to be reimplemented in derived classes
virtual bool isHand() const { return false; }
virtual bool isHead() const { return false; }
// in Hand (similar to what will be in Head)
bool isHand() const { return true; }
// How to use:
BodyPart::pointer ptr = humanBodyVector[42]; // one item from the array
if(ptr->isHand())
processHand(/*cast to hand*/)
else if(ptr->isHead())
// ...
Example 2: let the derived classes handle the cast
// in BodyPart; to be reimplemented in derived classes
virtual Hand* toHand() const { return 0; }
virtual Head* toHead() const { return 0; }
// in Hand (similar to what will be in Head)
Hand* toHand() const { return this; }