Say I have such classes:
class Scene {
public:
Scene(void);
~Scene(void);
virtual void update(void) = 0;
virtual void construct(void) = 0;
virtual void destroy(void) = 0;
};
class KillTheHedgehogScene : public Scene {
public:
virtual void update(void) override;
virtual void construct(void) override;
virtual void destroy(void) override;
EntitySceneGraph sceneGraph;
};
and I have a SceneManager class that goes something like this:
class SceneManager {
public:
SceneManager(void);
void loadNewScene(Scene* scene);
Scene* getCurrentScene(void);
void update(void);
private:
Scene* _currentScene;
};
The way my code functions now, I would load a new scene by doing the following:
_sceneManager->loadNewScene(new KillTheHedgehogScene());
My issue with this is that whatever scope this is in has made the allocation, and now _sceneManager has to be in charge of it's deallocation. I want the SceneManager to handle both allocation and deallocation. I want to be able to call my loadNewScene() function in this way:
_sceneManager->loadNewScene<KillTheHedgehogScene>();
This way the scene manager can handle both the allocation and deallocation of the object, and gives it all control. My question however is how can I have templates restrict an input type based on inheritance. For example, I wouldn't want to be able to call:
_sceneManager->loadNewScene<SomeRandomOtherClass>();
SomeRandomOtherClass is not a child class of Scene. Is there a way to restrict the type?
To have a better error message when providing invalid template parameter, you may add static_assert, something like:
template <typename T>
void loadNewScene()
{
static_assert(std::is_base_of<Scene, T>::value, "Type should inherit from class Scene");
// Your implementation
}
Related
I got an object tree. In the object tree I store SceneNodes. A SceneNode is usually the base class for other classes.
I want to implement different behavior for the objects that represent the SceneNodes.
The correct Pattern for this problem should be the visitor pattern. I want to iterate over the SceneNodes and want to call different functions based on the objects stored behind the SceneNodes.
But I not only want to allow one object in the object tree to be one component of the visitor pattern but to share functionality.
For example: I have a BaseObject. I can update this BaseObject (e.g. to a new position) and I can draw a BaseObject (OpenGL stuff).
But I also have a Camera object. The camera object can be updated but not drawn.
Here is the implementation of the Visitor Stuff:
class Visitor
{
public:
virtual void VisitUpdate(ComponentUpdate* element) = 0;
virtual void VisitDraw(ComponentDraw* element) = 0;
virtual void VisitOverlay(ComponentOverlay* element) = 0;
};
Visitor Component:
class Component
{
public:
virtual ~Component() { }
virtual void accept(Visitor* visitor) = 0;
};
Concrete Component:
class ComponentUpdate : public Component
{
public:
void accept(Visitor* visitor) override {
visitor->VisitUpdate(this);
}
virtual void update() = 0;
};
class ComponentDraw : public Component
{
public:
void accept(Visitor* visitor) override {
visitor->VisitDraw(this);
}
virtual void draw() = 0;
};
And finally a concrete visitor:
class SceneNodeVisitor : public Visitor
{
void VisitUpdate(ComponentUpdate* element) override {
element->update();
}
void VisitDraw(ComponentDraw* element) override {
element->draw();
}
};
Now I'd like to do something like this:
class Camera : public ComponentUpdate
{
void update() override { std::cout << "Camnera update" << std::endl; }
};
class ObjectBase : public ComponentDraw, public ComponentUpdate
{
void update() override { std::cout << "ObjectBase update" << std::endl; }
void draw() override { std::cout << "ObjectBase draw" << std::endl; }
};
Ok, so far so good. The problem I have now is that the compiler says "base class is ambiguous". I think this is not correct because ObjectBase is ambiguous because it has two different accept() functions, am I right?
Is there a way to use the visitor pattern so that I can freely anoint the classes with the functionality I need for them?
Here the main function:
int main() {
ObjectBase ob;
Camera cam;
SceneNodeVisitor visitor;
std::vector<Component*> components;
components.push_back(new Camera);
components.push_back(new ObjectBase);
components[0]->accept(&visitor);
components[1]->accept(&visitor);
}
Strange is that I can create the ObjectBase on the stack. I only get the error if I try to create the object on the heap (via new).
Pastebin is down at the moment, I can give you this example code as soon as it's up again.
Okay, I'm not entirely sure, but I think you should separate out some of the concepts you're doing.
As soon as you inherit from two classes that both inherit from the same base class, you need to start looking at virtual inheritance. That might solve your problem. But the path from ObjectBase to Component is either through ComponentDraw or ComponentUpdate. In effect, you probably have two copies of Component because you're not using virtual inheritance.
I would strongly consider using the concept of interfaces. While C++ technically doesn't have them, you can make them, anyway.
And look at virtual inheritance.
I have an object "World obj;" that has a normal interface of methods for it's typical funcitonality, but I want to have an additional interface of methods specifically for initializing that should only be visible when I specifically need them.
An example might be like this:
class World{
public:
void draw();
void update();
void normalStuff();
void addATree(); // this should not be ordinarily available or visible,
void addACar(); // calling this might break the object
void addAClown();// if it's not in a ready state for it
private:
int m_data;
};
Is there a way to relatively hide addATree(); etc in a way that makes sense? Ideally the mechanism for revealing those methods would also put the object into a ready state for them, or at least fault if it's not possible.
Different approaches would be possible:
Don't change the code, just change the spec
No need to change the code. Change the API specification and if the caller throws garbage in he gets garbage out.
Make the functions check if they are allowed
Always safe.
class World{
public:
...
void addAClown() {
if(not allowed)
throw error or crash or output error message or just return;
else {
do the work;
}
}
private:
int m_data;
};
Write a function that only exposes the Interface if allowed
You can't protect against someone getting the interface early and use it longer than allowed.
You could extract the interface functions into a separate class.
class WorldInterfaceToProtect {
public:
void addATree() = 0; // this should not be ordinarily available or visible,
void addACar() = 0; // calling this might break the object
void addAClown() = 0;// if it's not in a ready state for it
};
then the main class can protect these functions.
class World : protected WorldInterfaceToProtect {
public:
void draw();
void update();
void normalStuff();
protected:
void addATree(); // this should not be ordinarily available or visible,
void addACar(); // calling this might break the object
void addAClown();// if it's not in a ready state for it
private:
int m_data;
};
You then need to add a function that exposes the interface.
class World ... {
public:
WorldInterfaceToProtect *GetInterface() { return allowed_cond ? this : nullptr; }
...
}
Separate the class itself and the builder
This only helps if the functions to be called are only allowed during construction and not later. Depending on the design of the builder you can get a good protection.
class World{
friend class WorldBuilder;
public:
void draw();
void update();
void normalStuff();
protected:
void addATree(); // this should not be ordinarily available or visible,
void addACar(); // calling this might break the object
void addAClown();// if it's not in a ready state for it
private:
int m_data;
};
class WorldBuilder {
static World *Build(...);
}
Perhaps split the world into more composable parts:
struct WorldInterface
{
virtual void draw() = 0;
virtual void update() = 0;
virtual void normalStuff() = 0;
};
class World : public WorldInterface
{
public:
void draw() override { /* actual drawing here */};
void update() override {};
void normalStuff() override {};
private:
int m_data;
};
class TreeWorld : public WorldInterface
{
public:
// takes a reference to the actual world engine and defers work to
// that
TreeWorld(World& worldEngine) : worldEngine_(worldEngine) {}
void draw() override { worldEngine_.get().draw(); };
void update() override { worldEngine_.get().update(); };
void normalStuff() override { worldEngine_.get().normalStuff(); };
void addATree() {
//do tree/world interaction here
}
private:
std::reference_wrapper<World> worldEngine_;
};
class CarWorld : public WorldInterface
{
public:
// takes a reference to the actual world engine and defers work to
// that
CarWorld(World& worldEngine) : worldEngine_(worldEngine) {}
void draw() override { worldEngine_.get().draw(); };
void update() override { worldEngine_.get().update(); };
void normalStuff() override { worldEngine_.get().normalStuff(); };
void addACar() {
//do car/world interaction here
}
private:
std::reference_wrapper<World> worldEngine_;
};
extern void play_tree_game(TreeWorld world);
extern void play_car_game(CarWorld world);
int main()
{
World worldEngine;
// initialise engine here
// play tree-phase of game
play_tree_game(TreeWorld(worldEngine));
// play car phase of game
play_car_game(CarWorld(worldEngine));
}
Good answers all around, I'll just add this because it was missing(?)
class World{
public:
void draw();
void update();
void normalStuff();
private:
int m_data;
};
class BuildableWorld : public World
{
public:
void addATree();
void addACar();
void addAClown();
};
Use the BuildableWorld at initialization phase and then just give a pointer to the base class type for others to use.
Sure, you need some way to give the "built" data for the base class to access, but that was not the issue here, right?
an alternative approach that has not been mentioned so far, may be to let addX() functions take parameters whose existence implies that World is in a valid state. Say, if you cannot add trees to a world without water, let World return an (optional) water object to pass to addTree ... in other words, you need to properly formalize World invariants:
class World{
public:
void normalStuff();
auto getAvaliableWaterBuckets() -> optional<WaterBuckets>;
auto getAvaliableSoil() -> optional<SoilPack>;
//...
void addATree( WaterBuckets&&, SoilPack&& );
//...
};
// in the meanwhile, in user land:
if( auto water = world->getAvaliableWaterBuckets() )
if( auto soil = world->getAvaliableSoil() )
world->addTree( std::move(*water), std::move(*soil) );
else
world->recycleWater( std::move(*water) );
the benefit of this approach is that the user is not forced to think about world state validity ( an error prone task ), he just thinks about what he needs in order to add a tree ( simpler, hard to use incorrectly ). Moreover, this scales well because addX() functions can share different objects ( addFlowers needs water, ... ) enabling the correct management of a possibly complex internal world state.
Of course, IMHO, if you need to use addX() strictly on world construction only ( and you don't plan to add trees later ), then the factory approach already mentioned in the comments seems the way to go ...
What I would like to do is place a manager into a map, and then call functions correlating to each manager. Because I have different types of managers I created a base class like so:
class iGyroManager {
public:
iGyroManager() {}
virtual ~iGyroManager() = default;
virtual bool preInit() = 0;
virtual bool init() = 0;
virtual bool postInit() = 0;
virtual void update() = 0;
virtual void cleanup() = 0;
}
Pretty straight forward and obviously works like a charm.
Then I do the following to create a derived class:
class GyroAudioManager : public iGyroManager {
public:
GyroAudioManager();
~GyroAudioManager() override;
bool preInit() override;
bool init() override;
bool postInit override;
void update() override;
bool cleanup() override;
}
Again, simple and straight forward. The cpp is very basic and just declares the bare functions.
I then create one final derived class:
class GyroAppStateManager : iGyroManager {
private:
std::map<int, iGyroManager&> m_managerMap;
public:
GyroAppStateManager();
~GyroAppStateManager() override;
bool preInit() override;
bool init() override;
bool postInit() override;
int start();
void update() override;
bool registerManager(iGyroManager& manager);
bool cleanup() override;
}
That seems to work, but it's in the registerManager function where it falls apart:
bool GyroAppStateManager::registerManager(iGyroManager& manager) {
// Try to insert a derived class into a base class map using what
// should be working.
m_managerMap.insert(1, manager);
return true;
}
And in the calling function:
int start() {
GyroAudioManager m_audioManager = GyroAudioManager();
mp_appStateManager->registerManager(m_audioManager);
/* use mp_appStateManager here, while m_audioManager is alive */
}
Except this does not seem to work at all and spits out the following:
error: no matching function for call to std::map<int, iGyroManager&>::insert(int, iGyroManager&)
So my question is what am I doing wrong? As I mentioned above, I'd like to add multiple different manager classes that derive a single base class to this map and then be able to run certain functions from it.
Is there actually a way of doing it?
You can't have a standard container of references. I'm still looking for the exact wording of the restriction, but in the meantime you might want to try std::reference_wrapper instead, or a container of (smart) pointers, which also allows polymorphism.
Actually, value_type is std::pair<key_type, mapped_type> which is an object type even when mapped_type is a reference. So that's ok.
The error is caused because the parameter to std::map<Key,Value>::insert is a pair<Key,Value>, not two separate arguments. Try
m_managerMap.insert({1, manager});
But then you need to arrange to reference an object that isn't destroyed immediately afterward, when start() returns.
I have a pure virtual class Interface:
class Interface {
public:
virtual ~Interface() noexcept;
virtual void open()=0;
virtual void close()=0;
protected:
explicit Interface(const string params);
string params_;
}
I then have an abstract class where I implement my business logic:
template<typename T>
class AbstractInterface : public Interface {
public:
void open() override;
void close() override;
void read_is_complete(const vector<byte_array>);
protected:
explicit AbstractInterface(const string params);
virtual ~AbstractInterface() noexcept;
}
Then there is the implementation for the interface that uses CRTP for polymorphism:
class SPInterface : public AbstractInterface<SPInterface> {
public:
explicit SPInterface(const string params);
virtual ~SPInterface() noexcept;
void open();
void close();
void read_is_complete(const vector<byte_array> data);
}
I have a unit test where I create an instance of SPInterface:
unique_ptr<Interface> intf;
intf.reset(new SPInterface("aaa"));
Letting this get out of scope calls the destructor AbstractInterface which in turn calls the close method on AbstractInterface and then it segfaults on this:
template<typename T>
void AbstractInterface<T>::close() {
static_cast<T *>(this)->close();
params_ = "";
}
Which is confusing as I already created an instance of the class. lldb seems to confirm:
AbstractInterface<SPInterface>::close(this=<unavailable>)
Letting this get out of scope calls the destructor AbstractInterface which in turn calls the close method on AbstractInterface and then it segfaults on this:
template<typename T>
void AbstractInterface<T>::close() {
static_cast<T *>(this)->close();
params_ = "";
}
It seems that you are trying to invoke a method of a derived class from within the destructor of a base class.
This is not safe at all and a segfault is the way the executable has to tell you that it doesn't approve that. :-)
Even though CRTP allows you to invoke a member function that belongs to the derived class on a (let me say) living object, it doesn't change the way an object is destructed.
Do not forget that bases and members are destroyed in the reverse order of the completion of their constructor.
I have a class called "OpenGLCamera"
and there is another class that needs a camera so at the moment he has OpenGLCamera (since the class is used as a type)
like so:
void draw(const OpenGLCamera& camera);
But i want it to be more general, so i want it to be
void draw(const SomeCamera& camera);
and this "SomeCamera" should be a pointer/reference or something to OpenGLCamera ofcourse!
I have a class called "Visual_settings".. and i heared i should use inheritance to achieve this... but i dont understand how.. how to do this? in the class Visual_Settings? Make it a base class of... and then??
Visual_Settings.h
#include "OpenGLCamera.h"
class Visual_Settings : public OpenGLCamera
{
};
Thanks in advance
The generic type that you are looking for which is SomeCamera, then OpenGLCamera should derive from this type SomeCamera. If you cannot do that then you need to use Adapter pattern. This would make sense if you have other types of cameras.
class SomeCamera
{
public:
virtual void Dowork()=0;
};
class OpenGLCamera : public SomeCamera
{
public:
virtual void Dowork() override
{
//use camera
}
};
//Approach 2 (bridge pattern): when you cannot modify OpenGLCamera:
//***Use proper constructors/destructors and initialize base class constructors as required
class SomeCamera
{
public:
virtual void Dowork()=0;
};
class OpenGLCamera
{
public:
void OpenGlDowork()
{
//use camera
}
};
class OpenGLCameraAdapter : public SomeCamera, OpenGLCamera
{
public:
virtual void Dowork() override
{
//use camera
OpenGlDowork();
}
};
OpenGLCamera should be inherited from SomeCamera.
SomeCamera should have interface, that will be overriden in OpenGLCamera.