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

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.

Related

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

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...

Creating a new object by calling the new constructor with a string

I was recently in a job interview and my interviewer gave me a modeling question that involved serialization of different shapes into a file.
The task was to implements shapes like circle or rectangles by first defining an abstract class named Shape and then implements the various shapes (circle, rectangle..) by inheriting from the base class (Shape).
The two abstract methods for each shape were: read_to_file (which was supposed to read the shape from a file) and write_to_file which supposed to write the shape into a file.
All was done by the implementation of that virtual function in the inherited shape (Example: For Circle I was writing the radius, for square I saved the side of the square....).
class Shape {
public:
string Shape_type;
virtual void write_into_file()=0;
virtual void read_into_files()=0;
Shape() {
}
virtual ~Shape() {
}};
class Square: public Shape {
public:
int size;
Square(int size) {
this->size = size;
}
void write_into_file() {
//write this Square into a file
}
void read_into_files() {
//read this Square into a file
}
};
That was done in order to see if I know polymorphism.
But, then I was asked to implement two functions that take a vector of *shape and write/read it into a file.
The writing part was easy and goes something like that:
for (Shape sh : Shapes) {
s.write_into_file();
}
as for the reading part I thought about reading the first word in the text (I implemented the serializable file like a text file that have this line: Shape_type: Circle, Radius: 12; Shape_type:Square...., so the first words said the shape type). and saving it to a string such as:
string shape_type;
shape_type="Circle";
Then I needed to create a new instance of that specific shape and I thought about something like a big switch
<pre><code>
switch(shape_type):
{
case Circle: return new circle;
case Square: return new square
......
}
</pre></code>
And then, the interviewer told me that there is a problem with this implementation
which I thought was the fact that every new shape the we will add in the future we should also update int that big swicht. he try to direct me into a design pattern, I told him that maybe the factory design pattern will help but I couldn't find a way to get rid of that switch. even if I will move the switch from the function into a FactoryClass I will still have to use the switch in order to check the type of the shape (according to the string content i got from the text file).
I had a string that I read from the file, that say the current type of the shape. I wanted to do something like:
string shape_type;
shape_type="Circle";
Shape s = new shape_type; //which will be like: Shape s = new Circle
But I can't do it in c++.
Any idea on what I should have done?
In you factory you could map a std::string to a function<Shape*()>. At startup you register factory methods will the factory:
shapeFactory.add("circle", []{new Circle;});
shapeFactory.add("square", []{new Square;});
shapeFactory.add("triangle", []{new Triangle;});
In your deserialization code you read the name of the type and get its factory method from the factory:
std::string className = // read string from serialization stream
auto factory = shapeFactory.get(className);
Shape *shape = factory();
You've now got a pointer to the concrete shape instance which can be used to deserialize the object.
EDIT: Added more code as requested:
class ShapeFactory
{
private:
std::map<std::string, std::function<Shape*()> > m_Functions;
public:
void add(const std::string &name, std::function<Share*()> creator)
{
m_Functions.insert(name, creator)
}
std::function<Shape*()> get(const std::string &name) const
{
return m_Functions.at(name);
}
};
NOTE: I've left out error checking.
In C++, with
for (Shape sh : Shapes) {
s.write_into_file();
}
you have object slicing. The object sh is a Shape and nothing else, it looses all inheritance information.
You either need to store references (not possible to store in a standard collection) or pointers, and use that when looping.
In C++ you would to read and write some kind of type tag into the file to remember the concrete type.
A virtual method like ShapeType get_type_tag() would do it, where the return type is an enumeration corresponding to one of the concrete classes.
Thinking about it, though, the question was probably just getting at wanting you to add read and write functions to the interface.
You could create a dictionary of factory functions keyed by a shape name or shape id (shape_type).
// prefer std::shared_ptr or std::unique_ptr of course
std::map<std::string, std::function<Shape *()>> Shape_Factory_Map;
// some kind of type registration is now needed
// to build the map of functions
RegisterShape(std::string, std::function<Shape *()>);
// or some kind of
BuildShapeFactoryMap();
// then instead of your switch you would simply
//call the appropriate function in the map
Shape * myShape = Shape_Factory_Map[shape_type]();
In this case though you still have to update the creation of the map with any new shapes you come up with later, so I can't say for sure that it buys you all that much.
All the answers so far still appear to have to use a switch or map somewhere to know which class to use to create the different types of shapes. If you need to add another type, you would have to modify the code and recompile.
Perhaps using the Chain of Responsibility Pattern is a better approach. This way you can dynamically add new creation techniques or add them at compile time without modifying any already existing code:
Your chain will keep a linked list of all the creation types and will traverse the list until it finds the instance that can make the specified type.
class Creator{
Creator*next; // 1. "next" pointer in the base class
public:
Creator()
{
next = 0;
}
void setNext(Creator*n)
{
next = n;
}
void add(Creator*n)
{
if (next)
next->add(n);
else
next = n;
}
// 2. The "chain" method in the Creator class always delegates to the next obj
virtual Shape handle(string type)
{
next->handle(i);
}
);
Each subclass of Creator will check if it can make the type and return it if it can, or delegate to the next in the chain.
I did create a Factory in C++ some time ago in which a class automatically registers itself at compile time when it extends a given template.
Available here: https://gist.github.com/sacko87/3359911.
I am not too sure how people react to links outside of SO but it is a couple of files worth. However once the work is done, using the example within that link, all that you need to do to have a new object included into the factory would be to extend the BaseImpl class and have a static string "Name" field (see main.cpp). The template then registers the string and type into the map automatically. Allowing you to call:
Base *base = BaseFactory::Create("Circle");
You can of course replace Base for Shape.

Circular dependency conundrums

In my C++ project, I have an Engine class, a Renderer class and an Object class.
The instance of Renderer renders instances of Object. However instances of Object add themselves or remove themselves from the list of things to render.
From a usability point of view, it should be possible to set whether an instance of Object is drawn or not from the Object, but without the circular dependency.
I have a possible solution to this problem, but I do not know if it is a good idea:
The update cycle in the game is done through an Update() function in the Engine class that calls the Update() functions for every object. When it comes to call the Update() function for each instance of Object, I could set it to check for two boolean variables in the Object class. One, for whether it should be drawn, and one for whether it is actually being drawn. This should thus allow for an instance of Object to be added or removed from the list of things to render as required.
Is it a good idea to do it this way? Is this way efficient or is there a better way without the circular dependency?
EDIT:
I have rewritten my question for greater clarity and moved the second part to a new question where it was probably more relevant and to avoid confusing things further here.
You would want Object to inherit from Rendered, and Renderer to only be aware of Rendered, not Object (See below):
#include <iostream>
#include <list>
struct Renderer;
struct Rendered
{
virtual void renderMe( Renderer& ) = 0;
protected:
//Renderer won't delete me...
virtual ~Rendered(){}
};
struct Object : Rendered
{
virtual void renderMe( Renderer& )
{
std::cout << "I'm rendered!" << std::endl;
}
};
struct Renderer
{
void add( Rendered& r )
{
renderList_.push_back( & r );
}
void remove( Rendered& r );//...use your imagination
void render()
{
for( std::list<Rendered*>::iterator i = renderList_.begin(); i != renderList_.end(); ++i )
{
(*i)->renderMe( *this );
}
}
private:
std::list<Rendered*> renderList_;
};
struct Engine
{
Renderer& renderer_;
Object myObject_;
Engine( Renderer& r )
: renderer_( r )
{
renderer_.add( myObject_ );
}
~Engine()
{
renderer_.remove( myObject_ );
}
};
int test()
{
Renderer r;
Enginer e( r );
r.render();
return 0;
}
Not sure I really understand the intention. However, i would like to revisit your original question:
Currently, in order for an instance of Object to be drawn, it needs to
add itself to the instance of Renderer's list of objects to draw. This
means it needs a pointer to the instance of Renderer, however Renderer
also needs to know about Object in order to draw it.
Why is this a problem? If you just need pointers, you can declare the class type upfront:
class Object;
class Renderer;
class Engine;
Although, even cleaner would be using an Interface class.
EDIT:
Do I understand correctly, the problem is that you want to pass Rendered instance to Object, so the object can paint itself using the renderer?
What about the Interface class then:
class Paintable
{
public:
virtual void paint(Renderer *) = 0;
};
class Object : public Paintable
{
...
}
All your paintable object will be extending from the interface. This way the Renderer class doesn't need to hold vector of Objects, but vector of pointers to Paintable. (e.g. Renderer is no longer dependent on Object)
ANSWER: to second comment
Not sure you have a choice. You need the rendering piece of code to have access to Object's internal data (color, position, etc ...) and to the Renderer handle. Your choices are have the code in Renderer accessing object's internal data. This is, I think, a bad idea, as the Renderer would need to have different code handling different objects, and also possibly accessing private members of the Object. The other way around is to have intelligent objects that can render themselves given the Renderer handle. So they can call: renderer.paintLine(...), etc. Using the Interface class is neat, as the Renderer doen't need to have any knowledge about the Objects it holds.

based on argument type, only matching object of container will be called

all,
I have a container of objects, e.g.,
class ShapeBase {};
class Rect: public Shape {
void set(class Diag diag);
};
class Circle: public Shape {
void set(class Radi radi);
};
now I have an application class to call this list of shapes. My intention is that
the element of the list will only be called based on argument type.
something like this.
class application {
typedef std::list<ShapeBase*> List;
List shapeList;
void set(class ???) {
for (List::iterator it = shapeList.begin(); it != shapeList.end(); ++it)
{
// with in the loop of all objects in list,
// only object with matching argument will be called
set(class ???);
};
so that the application class has no idea of concrete shape at all.
How to do that in C++?
Unfortunately, what you're trying to do with a list of objects is fairly difficult with the definitions as you've set them up. A problem with the settup is that there's no association of Rect to Diag at compile time, so you have to tell the compiler that Rectangles expect specific constructor arguments. One solution is to template the application::set method and then specialize that template for each Shape.
Below is some pseudo-code to do that (no guarantees on compiling):
template<typename ShapeType>
void fillShapeTypeList(std::list<ShapeType*> fillList) {
for (List::iterator it = this.shapeList.begin();
it != this.shapeList.end(); ++it) {
if (ShapeType *shape = dynamic_cast<ShapeType>(*it)) {
fillList.push_back(shape);
}
}
}
template<typename ShapeType, typename ShapeSetter>
void set(ShapeSetter setter) {
std::list<ShapeType*> fillList;
fillShapeTypeList(fillList);
for (std::list<ShapeType*>::iterator it = this.shapeList.begin();
it != this.shapeList.end(); ++it) {
(*it)->set(setter);
}
}
void set(Diag setter) {
set<Rect, Diag>(setter);
}
void set(Radi setter) {
set<Circle, Radi>(setter);
}
There is another much, much more complicated way to get this to work without the Rect/Circle specific setters using 'Substitution Failure is not an Error' patterns -- but it's not worth the effort for this case.
In general you should ask yourself if you're doing the right thing when it's not obvious how to make the compiler do what you want. In this case you might be better off registering call backs for objects with an application or make all shapes of a specified type look at a central object for sizing information.

Function pointer to a non-static member function when the class type is unknown?

I'm working on a game project that features scratch-built controls rendered into an opengl context; things like buttons, scrollbars, listboxes, etc. Many of these controls are nested; for example, my listbox has a scrollbar, a scrollbar has 3 buttons, etc.
When a scrollbar changes value, I'd like it to call 'some' function (typically in it's parent object) that responds to the change. For example, if the listbox has a slider, it should instantiate the slider, then tell the new slider that it should call the listboxes 'onScroll(float)' function. All of the controls share a common base class, so I could have a 'base* parent' parent pointer, then do 'parent->onScroll(val)'. The problem though is what happens when the parent doesn't inheirit from base; there'd be no virtual onScroll() to follow through, so the top-level parent would have to periodically check to see if any of the child controls had changed value. This would also clutter up other controls, since they may not even have children, or may require different event types like when a list entry object is selected, etc.
A better solution would be to have the child object maintain a generic function pointer (like a callback), which can be set by the parent, and called by the child as necessary. Something like this:
typedef (*ptFuncF)(float);
class glBase {
public:
//position,isVisible,virtual mouseDown(x,y),etc
};
class glDerivedChild : public glBase {
public:
glDerivedChild();
~glDerivedChild();
void changeValue(float fIn) {
Value = fIn; //ignore these forward declaration errors
(*callBack)(fIn);
}
void setCallBack(ptFuncF pIn) {callBack = pIn;}
ptFuncF callBack;
float Value;
};
class glDerivedParent : public glBase {
public:
glDerivedParent() {
child = new glDerivedChild();
child->setCallBack(&onScroll);
}
~glDerivedParent() {delete child;}
void onScroll(float fIn) {
//do something
}
glDerivedChild* child;
};
class someFoo {
public:
someFoo() {
child->setCallBack(&setValue);
}
void setValue(float fIn) {
//do something else
}
glDerivedChild child;
};
I'm kinda new to function pointers, so I know I'm (obviously) doing many things wrong. I suspect it might involve something like "typedef (glBase::*ptFuncF)(float);" with the 'onScroll(f)' being an overridden virtual function, perhaps with a generic name like 'virtual void childCallBack(float)'. I'd prefer to keep the solution as close to vanilla as possible, so I want to avoid external libraries like boost. I've been scratching my head over this one for the better part of 8 hours, and I'm hoping someone can help. Thanks!
I think, what you want is some kind of events or signals mechanism.
You can study, how event processing is organized on Windows, for example. In short, your scrollbar generates new event in the system and then system propagates it to all elements, registered in the system.
More convenient mechanism is signal/slot mechanism. Boost or Qt provides such tools. I'll recomend this solution.
But if you still want to use just callbacks, I'll recommend using std::function (boost::function) (combined with std::bind (boost::bind), when required) instead of raw function pointers.
Use boost::function (or std::function if available). Like this (using your notation):
typedef std::function<void (float)> ptFuncF;
//...
void setCallBack(const ptFuncF &pIn);
//...
child->setCallBack(std::bind(&glDerivedParent::onScroll, this, _1));
//...
child->setCallBack(std::bind(&someFoo::setValue, this, _1));
A function pointer to a member function of a class has such a type:
<return type> (<class name>::*)(<arguments>)
For example:
typedef void (glBase::*ptFuncF)(float);
^^^^
by the way, you have forgot the `void` in your `typedef`
ptFuncF func = &glDerivedChild::onScroll;
And you use it like this:
glDerivedChild c;
(c.*func)(1.2);
In your particular example, the function is a member of the derived class itself, therefore you should call it like this:
(c.*c.callback)(1.2);
the inner c.callback is the function pointer. The rest is exactly as above, which is:
(class_instance.*function_pointer)(arguments);
You might want to take a look at this question also.
Ok, the workaround I came up with has some extra overhead and branching, but is otherwise reasonable.
Basically, each callback function is implemented as a virtual member function that recieves the needed parameters including a void* pointer to the object that made the call. Each derived object also has a base-class pointer that refers to the object that should recieve any events that it emits (typically its parent, but could be any object that inheirits from the base class). In case the control has multiple children, the callback function uses the void* pointer to distinguish between them. Here's an example:
class glBase {
public:
virtual onChildCallback(float fIn, void* caller);
glBase* parent;
};
class glSlider : public glBase {
public:
glSlider(glBase* parentIn);
void changeValue(float fIn) {
Value = fIn;
parent->onChildCallback(fIn, this);
}
float Value;
};
class glButton : public glBase {
public:
glButton(glBase* parentIn);
void onClick() {
parent->onChildCallback(0, this);
}
};
class glParent : public glBase {
public:
glParent(glBase* parentIn) : parent(parentIn) {
childA = new glSlider(this);
childB = new glButton(this);
}
void onChildCallback(float fIn, void* caller) {
if (caller == childA) {
//slider specific actions
} else if (caller == childB) {
//button specific actions
} else {
//generic actions
}
}
glSlider* childA;
glButton* childB;
};
Besides a reasonably small amount of overhead, the scheme is flexible enough that derived classes can ignore certain components or omit them altogether. I may go back to the function pointer idea later (thanks shahbaz), but half the infrastructure is the same for both schemes anyway and the extra overhead is minimal, especially since the number and variety of controls will be rather small. Having the callback function use a nested response is actually a little better since you don't need a separate function for each child object (eg onUpButton, onDownButton, etc).