I have an abstract Node
class, derived in many subclasses, such as Color
, Texture
, Shape
, Light
, etc... containing my application user data. The data consists in a large tree of these nodes.
Each Node
subclass has a fixed number of children, which are of fixed types. For instance, a Material could have one Color child, and one Texture child. These are stored as std::shared_ptr
's
Currently, each class derives a setChild
method, which takes a Node
as argument. Each implementation checks the type versus its children type with dynamic_cast
accordingly, and sets it if successful.
I would like to implement a generic setChild
method in Node
, without the need for subclassing it. For this, each subclass would declare (or register) its children in the constructor, by giving a name string, a type string (corresponding to the subclass) and a pointer to a shared_ptr
to a Node
.
You can see the problem now:
- I will use a
**SubClass
, upcast to an**Node
, which I know is bad, but since each subclass has atype()
method to uniquely identify the class, and since for each registered child I know its type, I can double check to avoid storing wrong pointer types with the double pointer. - I will do this in fact not with a
**Node
, but with a*std::shared_ptr<Node>
. Here I'm not sure of doing something right.
Questions:
- Is it possible to set a
shared_ptr<Subclass>
with a*shared_ptr<Node>
even if I'm sure of the type? - Is this designed the way you would have done it?
Thanks,
Etienne
If I understand you, the following is not safe:
Now you may get lucky and the memory may line up, but that is not valid C++.
If you are looking to extend the set of nodes in 3rd party plugins, the only solution is a series of dynamic casts, so lets see what we can do to make registration work with that.
Instead of trying to do everything with casts, consider using templates to do typesafe actions. Have an abtract base class which accepts a shared ptr to node, and either consumes it, or doens't consume it
(from here on out, I'm going to use T::Ptr instead of boost::shared_ptr, assuming that typedef is there. This is just for stackoverflow ease of reading)