Scene graph child node registration & copy constructor - c++

I have a scene graph, all nodes deriving from a base class AbstractNode. AbstractNode has a registerChild member function:
registerChild<T>(string name, shared_ptr<AbstractNode> * childMember)
used for registering the children in a standard way (so that they can be listed and modified in the base class interface). It basically adds the name/child_pointer pair to a hash.
So for instance the class material will be declared like that (shortened):
class Material : public AbstractNode
{
public:
Material() { registerChild(&color); }
private:
std_shared<Color> color;
}
Color being another subclass of AbstractNode.
Now I would like to implement a copy constructor for AbstractNode. It must copy the list of registered children, and update the child member pointers. I would like to avoid reimplementing the copy constructor in all base classes. Is this possible?
I have thought of working on pointer offsets, between this and the child pointers. But are these guaranteed to be constant between two instances? It seems like a big hack to me... (And I'm even sure that this is not guaranteed when subclassing)
Thanks,
Etienne

Related

where to declare the data that needs to be accessible to multiple objects?

I have just started to work with multiple objects/classes and I am having a hard time figuring out how to implement the data structure properly
Assuming I have a base class
class control
{
protected:
char* location
/* node** adjacency_list; This doesn't work */
};
and two different derived classes
class carA:public control
{
};
class carB:public control
{
};
and a node class.
My problem starts when I try to implement a 2D-ish structure like an array of linear linked list (graph) based on location in which the adjacency_list needs to point to the right memory space and must be available to all objects.
If I initialize the adjacency_list pointer to NULL at the base
class constructor, with every derived class object it will be set to
NULL again.
If I create the array in the base class constructor, it will create a
new array for every derived class object.
I tried to find a way with using the copy constructor of the base class in the derived class initialization list, but I couldn't justify/visualize a way that works.
So apart from declaring it globally, what/where is a simple, sensible way to declare this pointer?
I understand this might be extremely trivial, but I just can't see it at the moment.

C++ copy constructor issue with parent/child classes

I've run into a problem with copy constructors...I assume there is a basic answer to this and I'm missing something obvious - maybe I'm doing something entirely wrong - but I haven't been able to figure it out.
Basically, I have a parent class and child class. The parent class contains a vector of pointers to a (different) base class object. The child class wants to instead store pointers to objects derived from that base object.
Here's a pseudocode sample, if that helps:
// Base classes
class ItemRev {
...
}
class Item {
protected:
vector<ItemRev *> m_revPtrVec;
}
Item::Item(const Item &inputItemObj)
{
// Copy contents of the input object's item rev pointer vector
vector<ItemRev *>::const_iterator vecIter = (inputItemObj.m_revPtrVec).begin();
while (vecIter != (inputItemObj.m_revPtrVec).end()) {
(this->m_revPtrVec).push_back(new ItemRev(**vecIter));
}
}
=========
// Derived classes
class JDI_ItemRev : public ItemRev {
...
}
class JDI_Item : public Item {
...
}
JDI_Item::JDI_Item(const JDI_Item &itemObj)
{
// Copy contents of the input object's item rev pointer vector
vector<ItemRev *>::const_iterator vecIter = (inputItemObj.m_revObjPtVec).begin();
// The below does not work!
while (vecIter != (inputItemObj.m_revObjPtVec).end()) {
m_revObjPtVec.push_back(new JDI_ItemRev(**vecIter));
}
}
The problem with the above is in the push_back() call in the JDI_Item copy constructor.
Given this setup, what should the child class's copy constructor look like? Do I even need a child class copy constructor? I assumed I did, because the copy constructor is creating new objects, and the parent copy constructor will create new objects that are not the type I want in the derived class (i.e., the parent object stores pointers to ItemRev objects, while the child object should store pointers to derived JDI_ItemRev objects).
As mentioned in the comments, there is probably a more succinct way to express this problem (i.e. your class structure needs some work).
However, if you want to do it this way, the easiest way to achieve it is to use a virtual clone() method in the base class of ItemRev, with overrides of it defined in derived classes.
e.g.:
class ItemRev {
virtual ItemRev* clone() const = 0;
};
class JDI_ItemRev : public ItemRev {
ItemRev* clone() const override
{
// do your actual cloning here, using the copy constructor
return new ItemRev(*this);
}
};
Now, whenever you call clone() on any class derived from ItemRev, you will be returned an ItemRev* but it will point to a fully constructed derived class. You can of course get to the derived class's interface with static_cast<> or dynamic_cast<>.
...however...
derivation often seems like an easy win but it often turns out not to be. Inheritance should only be used if the derived class really is a type of the base class. Often people select inheritance when the derived class is a lot like a base class, or shares many characteristics with a base class. This is not the time to use inheritance. It's the time to use encapsulation.
In general, inheritance is evil.
On another note, you might find this link interesting.
Presentation on inheritance as an implementation detail

pointer to derived class in base class constructor

(Note that this is an oversimplification of my actual design.)
Given the following:
class CParentA;
class C_Child
public:
C_Child(C_ParentB* parent) : m_parent(parent){};
virtual ~C_Child();
CParentB* m_parent;
};
class C_ParentA : public C_Child
{
public:
C_ParentA(C_GrandParent *gp) : C_Child(gp){};
virtual ~C_ParentA(){};
}
class C_ParentB
{
public:
C_ParentB(){};
virtual ~C_ParentB(){};
void foo(){};
}
class C_GrandParent : public C_ParentB, public C_ParentA
{
public:
C_GrandParent() : C_ParentA(this){};
virtual ~C_GrandParent();
}
main()
{
C_GrandParent gp;
gp.m_parent->foo();
}
It seems that parentB's pointer, sent to the child's constructor, isn't valid yet when the grandparent is created. I had thought that, even if the parent wasn't fully constructed, it's pointer (this) would still be valid. I've also tried having ParentB be a pointer stored in the grandparent, and the object dynamically created in the grandparent constructor. But that apparently has the same outcome.
FWIW: the goal of this: grandparent has many parents, some of them with children. One child may need access to another child or a parent (uncle/cousin). I had thought that having them all under one patriarch would handle much of the inter-relationships between family members. While that is the case, setting the appropriate pointers seems to be the problem.
First, is is not clear what you are asking, so I am just trying to speculate. You present a design that is not working so you must be asking for alternatives, but you give no information on what you are trying to do.
Second, when class A derives a class B we usually say B is the base or parent and A is the derived or child. You use the opposite terminology and this is very confusing.
Now, I only assume that CParentB* m_parent; in C_Child is supposed to refer to the same C_Child object, viewed as CParentB. You don't need to store a pointer for this. Given a C_Child& r reference or C_Child* p pointer, you can simply say respectively
dynamic_cast<CParentB&>(r)
dynamic_cast<CParentB*>(p)
Both will fail in different ways if r,p do not refer to a CParentB object. dynamic_cast lets you navigate the entire class hierarchy and check at run time if a cast is valid. If the classes are not polymorphic, you can use static_cast instead.
In any case, keep in mind that before any object of a derived class is fully constructed, its bases need to constructed first. So before that, avoid playing in any way with the partially constructed object, like calling its methods especially virtual ones.

Inheritance of static object pools and constructors?

I'm working on a game / simulation, and dealing with managing all the creatures in the game.
There is one base class Creature from which different kinds of creatures take inheritance from.
In early versions of this code, where I just used the base class on its own as a generic for any given creature, I had a private static vector that kept a phonebook if you will of all the creatures that exist in the game. This was handled by the Creature's constructor, adding the new creature's address onto the stack. Simple enough.
Where I'm getting a mental block is when I introduce inheritance. If I proceed to adapt the Creature class to be a base class (move the vector to protected status I would imagine?), and from there define some arbitrary child classes of Monkey, Bear, and Tiger... When I create an instance of a class that inherits from Creature, will it -also- be added to the pointer vector in the Creature parent class? Perhaps more directly, does creating an instance of one of these child classes also call the constructor of the parent class?
Am I on the right train of thought, or what would I have to do to achieve this behavior?
I can provide more specific details if needed.
Thanks.
--
My idea behind doing things this way, for one example is graphics. That way I can cycle through all the creatures that exist and via polymorphism call functions on each of the creatures that return their sprites, X Y location, etc.
This definitely works, as long as your vector store pointers Creature* and not Creature inside your std::vector. Otherwise object slicing would occur since the vector reserve the space for just Creature and every additional feature of subclasses is discarded
Regarding the constructor call stack it is fairly straightforward:
class A {
private:
int aField;
public:
A(int aField) : aField(aField) { }
};
class B : public A {
private:
int bField;
public:
B(int aField, int bField) : A(aField), bField(bField) { }
};

Returning parent type in C++ interfaces

When using interfaces in c++; You have your abstract (parent) class. Then you have the child class which inherits from the parent class and implements the pure virtual functions.
When another class uses the (child) interface, what is the point in the abstract class at this point? If you try to use the parent type in a function, i.e returning the type Parent, you get compiler errors (presumably because the compiler doesn't know how much memory to allocate).
Can anyone tell me how to do the above?
i.e
Parent = Shape.
Child = Rectangle.
Thrid class which contains method which returns the type Shape?
Thanks in advance for any help/information.
A big advantage is that all children share the same interface. If you have a second child inheriting from the parent (Child = Circle), then regardless of the specific subclass, both of them can use the same functions.
Imagine then that you have a vector with pointers to shapes (vector < Shape* >), then it doesn't matter which shapes you have in the vector, if your base class Shape has a virtual method Draw(), you can use that method from each element of the vector without explicit knowledge how that Draw method is implemented.
You cannot instantiate an abstract class. Period. If you have a child that you want to access through a base-class interface, then you must access the child through a pointer or reference to the base class.
class A
{
public:
virtual void doit() = 0;
}
class B : public A
{
public:
virtual void doit()
{std::cout << "Hi.";}
}
...later, in main
A *a = new B;
a->doit(); //this calls B's implementation.
If you don't know why this is handy, you should research the term "polymorphism."
I think you are returning the objects on the stack, which doesn't work because you simply cannot instantiate abstract types:
Parent Child::foo() {
return Child(12);
}
That means, the compiler reserves (or rather, would reserve) the space for a Parent. And also try to copy construct Parents when calling foo.
What you probably meant was this:
Parent* Child::foo() {
return new Child(12); // actually you should really be using a shared pointer here, but that's a different story
}
This works, because the pointer to Parent and the pointer to Child have the size and alignment.
You can even directly return a Child because of co-variance. C++ allows you to implement Parent* Parent::foo(); as Child* Child::foo(); if Child inherits from Parent.