(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.
Related
A situation I often come up against is having a set of classes, Base and Derived, where the Base class has ownership of a base-class member BaseMember, and the Derived class has a reference or pointer to the same object, but as a DerivedMember.
For example, a UI panel class that contains a specific instance of a certain type of control with some special-control functions, inheriting from a general class that contains a general control and has general-control functions.
First, say that BaseMember is inherited by DerivedMemeber.
Without using smart pointers, I might do something like this:
class Base
{
protected:
// receive ownership but only because we say so,
// someone else can still try to delete as it's "just a pointer"
Base(BaseMember* _bmember):
bmember(_bmember)
{}
public:
virtual ~Base()
{
// perform an owner's duty
delete bmember;
}
// functions that might be based on BaseMember + other base state
void SetMemberId(....)
{
bmember->SetId(baz);
}
private:
int baz;
BaseMember* bmember; //owned, but not smartly
}
class Derived: public Base
{
public:
Derived(DerivedMember* _dmember):
Base(_dmember),
dmember(_dmember)
{}
// functions that only make sense for Derived + Derived/Base state
void SetDerivedFrobulation()
{
// only a DerivedMember has frobulation, so only
// Derived allows users to access it
dmember->setFrobulation(foo);
}
private:
int foo; // some state
DerivedMember* dmember; // no ownership here
}
With smart pointers (C++11 and up, specifically, I don't really care about older C++ in this case), I am tempted to do something like this and never let the Base/DerivedMember object out into dumb-pointer-land where it could leak if there was an exception somewhere inconvenient.
class Base
{
protected:
// receive ownership
Base(std::unique_ptr<BaseMember> _member):
member(std::move(_member))
{}
virtual ~Base()
{}
public:
// public access functions here as before
private:
std::unique_ptr<BaseMember> member;
}
class Derived: public Base
{
public:
// pass the ownership down by unique_ptr
Derived(std::unique_ptr<DerivedMember> _dmember):
Base(std::move(_dmember)),
dmember(_dmember.get()) // _dmember is moved! SEGFAULT if access dmember later!
{}
// public access functions here as before
private:
// handy handle to the derived class so we don't need to downcast the base (or even access it!)
DerivedClass* dmember
}
As I noted there, you can't "steal a peek" at the DerivedMember class as it comes in to the Derived constructor, because the unique_ptr is moved away before Derived gets a look in.
I can see a solution in providing a protected access to the BaseMember and static_casting back to DerivedMember in the Derived constructor (i.e. after the Base constructor is done), but this seems an ugly way to get access back to a variable we let slip though our fingers!
Another way could be each inheritor of Base owns the pointer, and base just gets a dumb pointer. In this case, the Base destructor doesn't get access to the member, as it's already gone. Also it would duplicate the ownership logic needlessly.
I think either:
This is symptomatic of an anti-pattern and the design of the whole Base/Derived/BaseMember/DerivedMember system is not good practice.
I'm missing a trick and there is a clean way to do this without fumbling a smart pointer and making a leak possible or adding functions and exposing interfaces or casting too much.
Is this a good pattern for re-use, or should I look elsewhere?
Expanding on the use case (EDIT)
In a core library, I have a class DataInterpreter which shows "some interpretation" of data - could be a string, an image, etc. This is then inherited by, amongst others, TextInterpreter which presents a string.
I then have a DataDisplayPanel class which represents a piece of UI for displaying in an abstract sense. Exactly what is in this panel will depend on the interpreter used: a TextInterpreter should get a text entry field and say a button to set some text display option, and that is handled in TextDisplayPanel, which has "special" knowledge of the text aspect of the interpreter.
There is then a DataAggregatePanel which combines a number of DataDisplayPanels and provides some global settings that affect all displays (via virtual functions), and manages the panels in a std::vector<std::unique_ptr<DataDisplayPanel> >. This aggregate class doesn't deal with any of the derived classes at all, any functions would be polymorphic and defined in the base.
In the application (which depends on the core library), these classes are extended (by inheritance or composition, whichever makes more sense). For example, if the application is a WX GUI, I might have wxDataAggregatePanel which contains wxTextDisplayPanel (and others), all of which are wxPanels. In this case, wxTextDisplayPanel might own a wxTextEntry and either own or inherit TextInterpreter and use its knowledge of the TextInterpreter's specific methods to fill the text box with a string.
You may use delegating constructor:
class Derived: public Base
{
public:
Derived(std::unique_ptr<DerivedMember> _dmember):
Derived(_dmember, _dmember.get())
{}
// public access functions here as before
private:
Derived(std::unique_ptr<DerivedMember>& _dmember, DerivedMember* ptr):
Base(std::move(_dmember)),
dmember(ptr)
{}
private:
// handy handle to the derived class so we don't need to downcast the base (or even access it!)
DerivedClass* dmember
};
I have two classes with a parent-child relationship (the Parent class "has-a" Child class), and the Child class has a pointer back to the Parent. It would be nice to initialize the parent pointer upon construction of the child, as follows:
class Child;
class Parent;
class Child
{
public:
Child (Parent* parent_ptr_) : parent_ptr(parent_ptr_) {};
private:
Parent* parent_ptr;
};
class Parent
{
public:
Parent() : child(this) {};
private:
Child child;
}
Now, I know people recommend not using this in initialization list, and C++ FAQ says I'm gonna get a compiler warning (BTW, on VS2010, I don't get a warning), but I really like this better then calling some set function in Parent's constructor. My questions are:
Is the parent this pointer well-defined when the Child object is being created?
If so, why is it considered bad practice to use it as above?
Thanks,
Boaz
EDIT: Thanks Timbo, it is indeed a duplicate (huh, I even chose the same class names). So lets get some added value: how about references? Is it possible / safe to do the following? :
class Child
{
public:
Child (Parent& parnet_ptr_) : parent_ptr(parent_ptr_) {};
private:
Parent* parent_ptr;
};
class Parent
{
public:
Parent() : child(*this) {};
private:
Child child;
}
Yes. It's safe to use this pointer in initialization-list as long as it's not being used to access uninitialized members or virtual functions, directly or indirectly, as the object is not yet fully constructed. The object child can store the this pointer of Parent for later use!
The parent this pointer, in "pointer terms", is well-defined (otherwise how would the parent constructor know on which instance is it operating?), but:
the fields that are declared after the Child object aren't initialized yet;
the code in the constructor hasn't run yet;
also, the usual warnings about using virtual members from the constructor apply1.
So, the parent object in general is still in an inconsistent state; everything the child object will do on construction on the parent object, will be done on a half-constructed object, and this in general isn't a good thing (e.g. if it calls "normal" methods - that rely on the fact that the object is fully constructed - you may get in "impossible" code paths).
Still, if all the child object do with the parent pointer in its constructor is to store it to be use it later (=> when it will be actually constructed), there's nothing wrong with it.
I.e., virtual dispatch doesn't work in constructors, because the vtable hasn't been updated yet by the derived class constructor. See e.g. here.
The behaviour is well-defined so long as you don't attempt to dereference the pointer until after the Parent object has been completely constructed (as #Sergey says in a comment below, if the object being constructed is actually derived from Parent, then all of its constructors must have completed).
Calling virtual methods in C++ is prohibited, however there are a few situations, where it might be very useful.
Consider the following situation - pair of Parent and Child classes. Parent constructor requires a Child class to be instantiated, because it has to initialize it in a special way. Both Parent and Child may be derived, such that DerivedParent uses DerivedChild.
There's a problem, however - because in Parent::ctor call from DerivedParent::ctor, base class should have an instance of DerivedChild instead of Child. But that would require calling a virtual method some way, what is prohibited. I'm talking about something like this:
class Child
{
public:
virtual std::string ToString() { return "Child"; }
};
class DerivedChild : public Child
{
public:
std::string ToString() { return "DerivedChild"; }
};
class Parent
{
protected:
Child * child;
virtual Child * CreateChild() { return new Child(); }
public:
Parent() { child = CreateChild(); }
Child * GetChild() { return child; }
};
class DerivedParent : public Parent
{
protected:
Child * CreateChild() { return new DerivedChild(); }
};
int main(int argc, char * argv[])
{
DerivedParent parent;
printf("%s\n", parent.GetChild()->ToString().c_str());
getchar();
return 0;
}
Let's get a real-world example. Suppose, that I want to write wrapper for WinApi's windows. The base Control class should register class and instantiate a window (eg. RegisterClassEx and CreateWindowEx), to properly set it up (for example register class in such way, that window structure has additional data for class instance; set up generic WndProc for all Controls; put reference to this by SetWindowLongPtr etc.)
On the other hand, derived class should be able to specify styles and extended styles, class name for window etc.
If constructing instance of window in the Control's constructor is a contract to be fulfilled, I see no other solution than to use VMs in ctor (what won't work).
Possible workarounds:
Use static polymorphism (eg. class Derived : public Base), but it will not work, if one wants to derive from Derived;
Pass a lambda from derived to base ctor if it is possible - it will work, but it's a total hardcore solution;
Pass a ton of parameters from derived to base ctor - it shall work, but won't be neither elegant, nor easy to use.
I personally don't like neither of them. Out of curiosity, I checked, how the problem is solved in Delphi's VCL, and you know what, base class calls CreateParams, which is virtual (Delphi allows such calls and guarantees, that they are safe - class fields are initialized to 0 upon creating).
How can one overcome this language restriction?
Edit: In response to answers:
Call CreateChild from the derived constructor. You're already requiring CreateChild to be defined, so this is an incremental step. You can add a protected: void init() function in the base class to keep such initialization encapsulated.
It will work, but it's not an option - quoting the famous C++ FAQ:
The first variation is simplest initially, though the code that actually wants to create objects requires a tiny bit of programmer self-discipline, which in practice means you're doomed. Seriously, if there are only one or two places that actually create objects of this hierarchy, the programmer self-discipline is quite localized and shouldn't cause problems.
Use CRTP. Make the base class a template, have the child supply the DerivedType, and call the constructor that way. This kind of design can sometimes eliminate virtual functions completely.
It's not an option, because it will work only once, for base class and its immediate descendant.
Make the child pointer a constructor argument, for example to a factory function.
This is, so far, the best solution - injecting code into base ctor. In my case, I won't even need to do it, because I can just parametrize base ctor and pass values from the descendant. But it will actually work.
Use a factory function template to generate the child pointer of the appropriate type before returning a parent. This eliminates the complexity of a class template. Use a type traits pattern to group child and parent classes.
Yea, but it has some drawbacks:
Someone, who derives from my classes may publish his ctor and bypass the security measures;
It would prevent one from using references, one would have to use smart pointers.
Calling virtual methods in C++ is prohibited, however there are a few situations, where it might be very useful.
No, calling a virtual method in the constructor dispatches to the most-derived complete object, which is the one under construction. It's not prohibited, it's well-defined and it does the only thing that would make sense.
A C++ base class is not allowed to know the identity of the most derived object, for better or worse. Under the model, the derived object doesn't start to exist until after the base constructors have run, so there's nothing to get type information about.
Some alternatives in your case are:
Call CreateChild from the derived constructor. You're already requiring CreateChild to be defined, so this is an incremental step. You can add a protected: void init() function in the base class to keep such initialization encapsulated.
Use CRTP. Make the base class a template, have the child supply the DerivedType, and call the constructor that way. This kind of design can sometimes eliminate virtual functions completely.
Make the child pointer a constructor argument, for example to a factory function.
Use a factory function template to generate the child pointer of the appropriate type before returning a parent. This eliminates the complexity of a class template. Use a type traits pattern to group child and parent classes.
My very first post here! I have been using this site for many years as a reference and to find solutions to common problems. Unfortunately this problem I am facing is one that have not been found here yet! So here it is. I have been working on a project for some time now. My program has several thousand lines of code so I will not post it all here. Basically, I have a subclass in which I wish to change the parent class to one that has been already initialized in my code some place. I am not sure if this is possible or if it is good code practice. But I will let you guys be the judge of that! Here is the problem I am facing:
#include <stdio.h>
class Base
public:
int data;
Base(int);
};
class Child : public Base
{
public:
Child(void);
void run(Base*);
};
Base::Base(int var)
{
data=var;
}
void Child::run(Base* base)
{
this = base //I know that you can create a reference to the parent class
//by casting this pointer to a Base pointer, but was wondering
//if you can do this the other way around.
printf("%d\n",Base::data);
}
int main()
{
Base* base1 = new Base(5);
Base* base2 = new Base(3);
Child one();
one.run(base1);
delete base1;
delete base2;
base1=0;
base2=0;
return 0;
}
So if this compiles(which it does not) it would outputt something like 5 and if I change the run method parameter to base2 it should print something like 3. Is this possible? Thank you!
No, you cannot do things like that. This is a READ-ONLY pointer. The line
this = base;
WILL generate a syntax error.
Base classes in C++ are static. They cannot be changed at run time.
Although, if your classes (both the base and the child) do not have virtual functions, the follwoing WILL work:
(Base&)*this = *base;
At the same time I would discourage you to do this. The reason of discouraging is because such code would be highly vulnerable for changes. For example, if virtual method will be added to either of the classes, then the VMT will be overwritten. This may not work with multiple inheritance. In my experiments with MSVC I noticed that sometimes it changes the order of base classes in the binary layout of the class.
In other words, this can be used if you are absolutely sure of the layout that is used by compiler. If you are sure that compiler will not change this layout in the future. If not, better avoid this.
The right approach is to create a special method and copy in the data field by field.
You cannot do precisely what you want, but you may be able to do something similar. If the parent class has a copy constructor, which lets you create an instance which is a copy of another instance, then you can use that copy constructor to create your parent object while your child object is being constructed:
class Child : public Base
{
public:
Child(const Base &b) : Base(b) { ...}
Now you have a Child object whose Base parts are identical to those of another Base object.
Consider this to be const. When you obtain a reference to the base class, you're simple obtaining a reference to some subset (portion) of the subclass; the base class instance is tightly bound to the class-as-a-whole (subclass instance in this case). You can direct how that base class is initialized (see Ernest's response), but you cannot break that link.
Usually the memory layout of a class-with-base-class is something like:
[ ... | base-class | ... ... .. ]
It's literally embedded, as opposed to existing independently (the following is not normal, I'd even go so far as to state it never happens - but that's an internal compiler choice):
[ ... | reference to-base-class | ... ... .. ] [ independent base-class instance ]
I have two classes with a parent-child relationship (the Parent class "has-a" Child class), and the Child class has a pointer back to the Parent. It would be nice to initialize the parent pointer upon construction of the child, as follows:
class Child;
class Parent;
class Child
{
public:
Child (Parent* parent_ptr_) : parent_ptr(parent_ptr_) {};
private:
Parent* parent_ptr;
};
class Parent
{
public:
Parent() : child(this) {};
private:
Child child;
}
Now, I know people recommend not using this in initialization list, and C++ FAQ says I'm gonna get a compiler warning (BTW, on VS2010, I don't get a warning), but I really like this better then calling some set function in Parent's constructor. My questions are:
Is the parent this pointer well-defined when the Child object is being created?
If so, why is it considered bad practice to use it as above?
Thanks,
Boaz
EDIT: Thanks Timbo, it is indeed a duplicate (huh, I even chose the same class names). So lets get some added value: how about references? Is it possible / safe to do the following? :
class Child
{
public:
Child (Parent& parnet_ptr_) : parent_ptr(parent_ptr_) {};
private:
Parent* parent_ptr;
};
class Parent
{
public:
Parent() : child(*this) {};
private:
Child child;
}
Yes. It's safe to use this pointer in initialization-list as long as it's not being used to access uninitialized members or virtual functions, directly or indirectly, as the object is not yet fully constructed. The object child can store the this pointer of Parent for later use!
The parent this pointer, in "pointer terms", is well-defined (otherwise how would the parent constructor know on which instance is it operating?), but:
the fields that are declared after the Child object aren't initialized yet;
the code in the constructor hasn't run yet;
also, the usual warnings about using virtual members from the constructor apply1.
So, the parent object in general is still in an inconsistent state; everything the child object will do on construction on the parent object, will be done on a half-constructed object, and this in general isn't a good thing (e.g. if it calls "normal" methods - that rely on the fact that the object is fully constructed - you may get in "impossible" code paths).
Still, if all the child object do with the parent pointer in its constructor is to store it to be use it later (=> when it will be actually constructed), there's nothing wrong with it.
I.e., virtual dispatch doesn't work in constructors, because the vtable hasn't been updated yet by the derived class constructor. See e.g. here.
The behaviour is well-defined so long as you don't attempt to dereference the pointer until after the Parent object has been completely constructed (as #Sergey says in a comment below, if the object being constructed is actually derived from Parent, then all of its constructors must have completed).