I am designing and entity-component system for a project, and C++ memory management is giving me a few issues. I just want to make sure my design is legitimate.
So to start I have an Entity class which stores a vector of Components:
class Entity
{
private:
std::vector<std::unique_ptr<Component> > components;
public:
Entity() { };
void AddComponent(Component* component)
{
this -> components.push_back(std::unique_ptr<Component>(component));
}
~Entity();
};
Which if I am not mistaken means that when the destructor is called (even the default, compiler created one), the destructor for the Entity, will call ~components, which will call ~std::unique_ptr for each element in the vector, and lead to the destruction of each Component, which is what I want.
The component class has virtual methods, but the important part is its constructor:
Component::Component(Entity parent)
{
parent.addComponent(this) // I am not sure if this would work like I expect
// Other things here
}
As long as passing this to the method works, this also does what I want. My confusion is in the factory. What I want to do is something along the lines of:
std::shared_ptr<Entity> createEntity()
{
std::shared_ptr<Entity> entityPtr(new Entity());
new Component(*parent);
// Initialize more, and other types of Components
return entityPtr;
}
Now, I believe that this setup will leave the ownership of the Component in the hands of its Parent Entity, which is what I want. First a small question, do I need to pass the entity into the Component constructor by reference or pointer or something? If I understand C++, it would pass by value, which means it gets copied, and the copied entity would die at the end of the constructor.
The second, and main question is that code based on this sample will not compile. The complete error is too large to print here, however I think I know somewhat of what is going on. The compiler's error says I can't delete an incomplete type. My Component class has a purely virtual destructor with an implementation:
inline Component::~Component() { };
at the end of the header. However since the whole point is that Component is actually an interface. I know from here that a complete type is required for unique_ptr destruction. The question is, how do I work around this? For reference I am using gcc 4.4.6.
Component::Component(Entity parent)
takes parent by calue so you add the component to this temporary, that will go away at end of function. And the original will miss this call. try
Component::Component(Entity &parent)
For the other part, you must ensure the type is complete where the template is instantiated.
The usual way is to declare the dtor in class as you do, and just put the implementation in the .cpp where the required types are defined. Inline is not really necessary.
Or you could include the other header before Entity, if in will not cause circular includes.
Related
Context
The context is composed by three classes:
abstract parent (e.g. Player)
child (e.g. TapePlayer)
a holder (e.g. MyMachine)
The holder has a member variable that is a shared_ptr<...> to the parent class and a setter for it accepts shared_ptr<...>s of children classes.
My getter looks something like this
shared_ptr<Parent> getChildPtr() {
return parentPtr;
};
but it returns a pointer to the parent, and cannot access child methods.
If I want to do something like the following
holder.getChildPtr()->childMethod();
// ERROR! No member named 'childMethod' in 'Parent'
How should I implement the getter to get the pointer to the child instead of the parent class?
Code
The whole code looks something like this:
class Player {
public:
Player(){};
virtual ~Player{};
virtual void play() = 0;
}
class TapePlayer : public Player {
public:
TapePlayer(){};
virtual ~TapePlayer{};
void play() { ... };
void rewind() { ... };
}
class MyMachine {
public:
MyMachine(); //
~MyMachine();
void setPlayer(shared_ptr<Player> p) {
playerPtr = p;
}
shared_ptr<Player> getPlayer() {
return playerPtr;
};
private:
shared_ptr<Player> playerPtr;
}
MyMachine machine; // the holder
shared_ptr<TapePlayer> tapePtr(new TapePlayer()); // pointer to child
machine.setPlayer(tapePtr); // set holder with pointer to child
machine.getPlayer()->rewind(); // -- ERROR! No member named 'rewind' in 'Player'
// if I want to get the player of that machine to rewind I need
// to dynamic_cast<TapePlayer>() ...
I'm pretty sure there's a better way of doing this than casting to children types. Any ideas?
EDIT
This was a very simplified example. What I'm actually trying to do is this:
My holder class is named Clip. A clip plays something, be it an
image, a video, a sequence of images, some kind of processing with
OpenCv, a vector shape... anything that can be displayed.
All these types of things are Players.
I don't care what type of player the clip holds. I just want it to show it to me. But, some players need tweaking at runtime, like the OpenCv one, that needs tweaking parameters for optimal processing. I cannot implement all methods of all subclasses in the parent class, that would make no sense to me. Why does a video need to have the methods for tweaking OpenCv parameters?
All I need is that both have 'playable' methods, and be able to store them in a map<string, PlayerPtr> to access them at any time or change the player the clip is holding.
The point is that this kind of ruins the polymorphism - even with dynamic_cast, you still need to check that the result is not 0 (i.e. check the actual type) and as you might already know, dynamic_cast is famous for being very slow (and requiring RTTI information built in the executable).
Is there any reason you couldn't add a pure virtual rewind() method to your Player interface? Then you'd just call it and the inherited class could do whatever it decides in that case. Other subclasses might implement it as empty (or it can be even empty by default in the Player itself, so that the subclasses do not have to implement it if they don't need to). Perhaps even some more "generic" virtual function like reset(), restart() etc. which would just call rewind() for the TapePlayer under the hood.
You can of course go even more fancy with more complex solutions like visitor/observer (TapePlayer being RewindObserver and observing a rewind event) etc.
EDIT:
So to address the edit comments - if the different types need tweaking, then again, you can just have a single virtual method tweak() (pure or with default empty impl) and do whatever tweaking is needed. Otherwise you'd anyway end up with a long list of ifs and call tweak methods depending on the actual type.
If the tweaking requires some special parameters, then the situation can be difficult ... one option could be to have a tweaking parameters interface (and call the tweak method with that), but if the params can't be unified you'd need a dynamic cast in the tweak method anyway to cast to the correct params type (this basically leads to double dispatch which in C++ requires casting at some point) ... but anyway that would still require to create different param classes in the calling site which is not that nice.
It also depends when you actually need to setup the tweaking parameters - if it is enough to setup everything when creating the instance (and the tweaking params do not change afterwards), or if it is needed to change them later on. If only needed to setup at startup, then you can have factory classes for the different object types and the factory can setup the params.
(technically you could handle even the necessity of changing the params a similar way, by keeping the setting object types for various player types, the players would keep reference to them as well, assigned when the objects are created, and once they need to be changed, you'd change the settings and call tweak() or update() or similar func to inform the objects that some setting changed and needs to be re-applied)
struct struct_unit{};
struct struct_unit_rotable : struct_unit {};
std::list <struct_unit> unitsList;
struct_unit *su=new struct_unit_rotable;
unitsList.push_front(*su);
then i have 2 draw methods:
void drawUnit(struct_unit &su);
void drawUnit(struct_unit_rotable &su);
when i call drawUnit(unitsList.front()); --- the WRONG nonrotable draw method is called
how to correctly insert
struct_unit_rotable type into list so the unitsList.front() will return type struct_unit_rotable?
You misunderstand polymorphism. The idea of polymorphism is to allow derived classes to provide implementations for methods declared virtual in a base class, but use pointer or reference to base class to access that implementation (if you use the objects directly, they will get sliced, see David's answer). In your case, there are no such declarations and hence no polymorphism.
To invoke polymorphism you would need
struct unit
{
virtual void draw();
virtual ~unit(); // important
};
struct unit_rotatable // did you really mean 'rotable'?
: unit
{
virtual void draw(); // 'virtual' needed only for another level of polymorphism
virtual ~unit_rotatable();
}
and invoke them via
std::list <std::unique_ptr<unit>> unitsList; // we need pointer (or reference) to base
unitList.emplace_front(new unit_rotatable);
unitList.front()->draw(); // calls unit_rotatable::draw()
I used unique_ptr to ensure the automatic de-allocation of the objects at the destruction of unitsList.
Your list will contain objects of type struct_unit. If you pass it objects of type struct_unit_rotable they will get sliced
Even if you use pointers only void drawUnit(struct_unit *su) will get called, you need to put the polymorphism into the structures as Walter has shown
as long as you insert the object as struct_unit, you'll always get this kind of object back and your drawUnit function called will always be the one for struct_unit. Aren't you able to move the drawUnit() function inside the object and make a class ? If you make the function virtual, you can have the correct one called.
This is quite an odd use of polymorphism.
A better way would be a virtual drawUnit() in struct_unit that will be overridden in struct_unit_rotable.
I do not have the standard at hand but I am sure that there is no proper way without casting to detect the most appropriate method as for the vector content it is of type struct_unit.
See here for a related issue: Matching an overloaded function to its polymorphic argument
It is stated that overload resolution is done at compile time. Your code would require overload resolution during execution time as it is not clear what type would be placed in the vector during compile time.
I see what you're trying to do. There is a very slick way to do this, introduced in this video which I would recommend anyone to study.
http://channel9.msdn.com/Events/GoingNative/2013/Inheritance-Is-The-Base-Class-of-Evil
[Inheritance Is The Base Class of Evil][1]
The basic premise here is that "inheritance should be an implementation detail, not an interface".
The more I have worked this way, the happier I have been that I have done so.
Suppose we have a class like this:
class OProcess {
...
void Process1();
void Process2(); // call only if Process1 wasn't called
...
}
such that function Process2() can be called only when function Process1() has NOT been called already.
Is there a way to check that Process class is used correctly at compile-time? I.e. compiler must give an error if Process1() CAN BE called before Process2() for some instance of OProcess object.
P.S. I understand that there can be code like this:
if (variable == 1000)
Process1();
Process2();
and compiler can't be sure that Process1() will be called before Process2(). But here compiler can be sure that Process1() CAN be called before Process2() for some values of variable. And I need it to make an error or at least warning.
The short answer is Somewhat.
The long answer is: C++ does not implement Linear Typing, thus uniqueness checks cannot be done at compile-time (fully). Still, reading this description gives us a trick: to implement this in the compiler, language designer forbid aliasing and enforce consumption.
So, if you agree that some runtime checks are allowed, then this can be done by having processes consume the object:
class OProcess {
public:
};
std::unique_ptr<OProcessed1> process1(std::unique_ptr<OProcess> op);
std::unique_ptr<OProcess> process2(std::unique_ptr<OProcess> op);
Where OProcessed1 is a proxy over OProcess presenting a restricted interface that exposes only those operations allowed on OProcess after that Process1 was called.
The runtime part of the checks is that:
void func(std::unique_ptr<OProcess> op) {
process1(std::move(op));
process2(std::move(op));
}
will compile, even though it is undefined behavior to do anything other than destruction/assignment to op after moving from it.
The correct way to do it is either make init private and reduce the risk you mention,
or use dependency injection, as 'init' methods, or any logic at all inside the constructor, are bad practice in terms of clean code
Another trick is to have ProcessBase that defines init and calls it in it's constructor. ProcessBase's constructor is called before the derived constructor, thus making sure that init is called before any logic is made in the derived class.
Edit:
You may want to change the logic to have both methods private and have one method called process3() that will call the other methods in the correct order.
Another option is to use the decorator design pattern and wrap one method in a class and have your decorator call them by order.
I've been searching all through the web and I seem to not find any alternate way of doing comparing if two polymorphic objects are the same type, or if a polymorphic object IS a type. The reason for this is because I am going to implement a Entity System inside of my game that I am currently creating.
I have not found another way of doing this other than with the use macros or a cast (the cast not being a portable method of doing so). Currently this is how I am identifying objects, is there a more efficient or effective way of doing this? (without the use of C++ RTTI)
I pasted it on pastebin, since pasting it here is just too much of a hassle.
http://pastebin.com/2uwrb4y2
And just incase you still do not understand exactly what I'm trying to achieve, I'll try to explain it. An entity in a game is like an object inside of the game (e.g. a player or enemy), it have have components attached to it, these components are data for an entity. A system in the entity system is what brings the data and logic of the game together.
For example, if I wanted to display a model up on the screen it would be similar to this:
World world; // Where all entities are contained
// create an entity from the world, and add
// some geometry that is loaded from a file
Entity* e = world.createEntity();
e->add(new GeometryComponent());
e->get<GeometryComponent>()->loadModel("my_model.obj"); // this is what I want to be able to do
world.addSystem(new RenderingSystem());
// game loop
bool isRunning = true;
while(isRunning)
{
pollInput();
// etc...
// update the world
world.update();
}
EDIT:
Here's a framework, programmed in Java, that does mainly what I want to be able to do.
http://gamadu.com/artemis/tutorial.html
See std::is_polymorphic. I believe boost has it too.
If T is a polymorphic class (that is, a class that declares or inherits at least one virtual function), provides the member constant value equal true. For any other type, value is false.
http://en.cppreference.com/w/cpp/types/is_polymorphic
Edit:
Why can't you just do this in your example?
Entity* e = world.createEntity();
GemoetryComponent* gc = new GeometryComponent();
gc->loadModel("my_model.obj");
e->add(gc);
Create the structure before stripping the type information.
If you're determined not to use C++'s built-in RTTI, you can reimplement it yourself by deriving all classes from a base class that contains a virtual method:
class Base {
public:
virtual string getType() = 0;
};
Then every derived class needs to overload this method with a version that returns a distinct string:
class Foo : public Base {
public:
string getType() { return "Foo"; }
};
You can then simply compare the results of calling getType() on each object to determined if they are the same type. You could use an enumeration instead of a string if you know up front all the derived classes that will ever be created.
Entity* e = world.createEntity();
e->add(new GeometryComponent());
e->get<GeometryComponent>()->loadModel("my_model.obj");
// this is what I want to be able to do
First the simple: there is a base type to all of the components that can be added, or else you would not be able to do e->add(new GeometryComponent()). I assume that this particular base has at least one virtual function, in which case the trivial solution is to implement get as:
template <typename T>
T* get() {
return dynamic_cast<T*>(m_component); // or whatever your member is
}
The question says that you don't want to use RTTI, but you fail to provide a reason. The common misundertandings are that RTTI is slow, if that is the case, consider profiling to see if that is your case. In most cases the slowness of dynamic_cast<> is not important, as dynamic_casts should happen rarely on your program. If dynamic_cast<> is a bottleneck, you should refactor so that you don't use it which would be the best solution.
A faster approach, (again, if you have a performance bottleneck here you should redesign, this will make it faster, but the design will still be broken) if you only want to allow to obtain the complete type of the object would be to use a combination of typeid to tests the type for equality and static_cast to perform the downcast:
template <typename T>
T* get() {
if (typeid(*m_component)==typeid(T))
return static_cast<T*>(m_component);
else
return 0;
}
Which is a poor man's version of dynamic_cast. It will be faster but it will only let you cast to the complete type (i.e. the actual type of the object pointed, not any of it's intermediate bases).
If you are willing to sacrifice all correctness (or there is no RTTI: i.e. no virtual functions) you can do the static_cast directly, but if the object is not of that type you will cause undefined behavior.
My gui application supports polymorphic timed events so that means that the user calls new, and the gui calls delete. This can create a problem if the runtimes are incompatible.
So I was told a proposed solution would be this:
class base;
class Deallocator {
void operator()(base* ptr)
{
delete ptr;
}
}
class base {
public:
base(Deallocator dealloc)
{
m_deleteFunc = dealloc;
}
~base()
{
m_deleteFunc(this);
}
private:
Deallocator m_deleteFunc;
}
int main
{
Deallocator deletefunc;
base baseObj(deletefunc);
}
While this is a good solution, it does demand that the user create a Deallocator object which I do not want. I was however wondering if I provided a Deallocator to each derived class: eg
class derived : public base
{
Deallocator dealloc;
public:
Derived() : base(dealloc);
{
}
};
I think this still does not work though. The constraint is that:
The addTimedEvent() function is part of the Widget class which is also in the dll, but it is instanced by the user. The other constraint is that some classes which derive from Widget call this function with their own timed event classes.
Given that "he who called new must call delete" what could work given these constraints?
Thanks
I suggest that you study the COM reference-counting paradigm (AddRef and Release). This allows more flexible lifetime and guarantees that the correct deallocator is used, because the object deletes itself.
Please note that if you're sharing class objects across DLL boundaries, you could have much bigger problems that just using the same allocator. There's the whole one-definition-rule to account for, and calling conventions, data layout, and name mangling schemes that differ between compilers. So if you want a reusable library, you really need to adopt the COM way of doing things with reference counting, self-deletion, and an interface containing only pure virtual functions. Whether you build real COM objects or your own COM-like system would depend on your other requirements.
The first thing that comes to mind is to give the base class a virtual (abstract?) SelfDestruct method. Assuming that the consumer of your DLL passes a class he derived himself, he will know how to deallocate it.
If he can pass classes which you have written, then you've got more problems. I suggest disallowing allocating such classes and providing a static method for allocating them with your own allocator.
I'm not sure if I've explained my idea very clearly... if not, please ask, I'll provide code later.
What could work with the given constraints is that you associate a deleter function-pointer with each TimedEvent, where both are specified as arguments to addTimedEvent.
To relieve the burden of the client to create a custom deleter function, you can provide an inline deleter function as a member of the anonymous namespace in the header of your widget class.
For example:
// Widget header
class base;
namespace {
inline void default_deleter(base* p)
{
delete p;
}
}
class Widget
{
public:
addTimedEvent(base* event, void(*deleter)(base*));
};
The advantage of the inline function is that it will be compiled in the context of the client code, so delete will also use a compatible deallocator as the client used to allocate the event.
Edit: Made the deleter function a member of the anonymous namespace. This is needed to avoid ODR violations.
Without the namespace, you get two functions default_deleter that have the same external name (so they are the same as far as the linker is concerned), but with different semantics, because they refer to different deallocators.
With the anonymous namespace, all instances of default_deleter become separate entities for the linker. This has the (unfortunate) side-effect that you can no longer use the function as a default argument to addTimedEvent.