I got assigned the task to clean up a class hierarchy, but I'm stuck in a bit of a rut. I'm now left with something that roughly looks like this:
class Base
{
Base() = 0;
function1();
...
function5();
protected:
int variable1_;
...
int variable10_;
};
class DerivedOne
: public Base
{
DerivedOne() = 0;
function6();
...
function10();
protected:
int variable11_;
...
int variable20_;
};
class DerivedTwo
: public DerivedOne
{
DerivedTwo()
: DerivedOne()
{
... Fill variable1_ to variable25_ with data read from file ...
variable1_ = ...
}
function11();
...
function15();
private:
int variable21_;
...
int variable25_;
};
So 25 variable are assigned their values in DerivedTwo, making it easy to make a mistake. When another class inherits from DerivedOne, it's almost certain that that person will forget to initialize one of the variables.
I've been playing around with different ways of designing this hierarchy, but nothing really feels right.
I understand it's difficult to say something concrete without knowing what these classes actually do, but I would be interested in knowing if there is something fundamental wrong with this design, or if I have overlooked some elegant way of initializing all the variables.
The principle in derivation is that base object is constructed first, and the derived afterwards. This requires the Base and DerivedOne constructor to produce a valid object on its own.
When constructing DerivedTwo, your code makes this clear:
DerivedTwo()
: DerivedOne() // First the base object constructor is called, before anything else
{
// then remaining initialisation, after DerivedOne() was created
}
So each class should at least initialise its own variables to an initial valid state that its own functions can handle in a consistent manner.
Base() : variable1_(/*default value here*/), variable10_(/*default value here*/) {}
Base(int v1, int v10) : variable1_(v1), variable10_(v10) {} // for convenience
One derived class could overwrite variables of its base class afterwards. It would of course be safer and more elegant to use getters/setters, but its ok.
If you adopt this design, if one subderived class forgets to initialise a variable one of its parents, this should not lead to a catastrophee because at least the base object is initialised in a decent manner.
Now the problem is that you also initiate your DerivedTwo by reading a file. Remember, first Base is created, then DerivedOne, and then only DerivedTwo reads the values. What happen when the file cannot be read or is unconsistent ? You might end up having an inconsistent object, unless your throw an exception. So you have to manage this and make sure that DerivedTwo is in a stable state:
DerivedTwo()
: DerivedOne() // First the base object constructor is called
{
// then initialise all own members to a consitent state
// then try to read the file and manage potential errors
}
Each class should be responsible for initializing its own data members. As you identified, it is dangerous for Base to assume that DerivedX will initialize its data members. So...
Base should initialize variable1_ ... variable10_
DerivedOne should initialize variable11_ ... variable20_
DerivedTwo should initialize variable21_ ... variable25_
...and so on.
Of course, this doesn't address the question of why the classes are laid out in such a fashion...
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
};
(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.
Having a member and pass the same to the base class works if:
DerrivedClass::DerrivedClass(SomeParamType* p)
: BaseClass(p),
derrivedClassMember(p),
{
...
}
... but how to share without passing it as param to the DerrivedClass constructor? Is this valid? Or is the derrivedClassMember not initialized at this time?
DerrivedClass::DerrivedClass()
: BaseClass(derrivedClassMember),
derrivedClassMember(new SomeParamType()),
{
...
}
I'm not able to change the base class implementation.
In C++11 you could use a delegating constructor:
class Derived : public Base {
public:
Derived() : Derived(new SomeParamType()) {}
...
private:
Derived(SomeParamType* p) : Base(p), derivedMember(p) {}
};
As a side note, I know this is probably just an example but you shouldn't create unmanaged objects on the heap like this in a constructor: if the Base constructor throws then you're in for a memory leak. Prefer smart pointers whenever possible.
I'm cringing as I write this, but....
DerrivedClass::DerrivedClass(SomeParamType* p = new SomeParamType())
: BaseClass(p),
derrivedClassMember(p)
{
}
I need to go shower now. Regardless, in deference to your question, yes, your base constructor should be executed before your members are initialized. Members have to be initialized in their top-down order, starting with the base members in its constructor and working out.
Note: I'd have to dust off my standard copy to find where this is specified, but I'm fairly sure its in there, as lint loves to tell you about out-of-order initialization warnings and their non-compliance.
It is not initialialized at that time. The baseclass constructor is called before the derrivedClassMember is initialized. That's because the derived members or the constructor of the derived class may depend on members of the baseclass.
To sum up the answers given up to now, and add a bit more, there are a few possible solutions.
1 If your base class has an accessor for the member, its fairly easy:
DerrivedClass::DerrivedClass()
: BaseClass(new SomeParamType()),
derrivedClassMember(getBaseClassMember()),
{
...
}
2 in C++11, use a delegating constructor, calling the original constructor you posted:
DerrivedClass::DerrivedClass()
: DerrivedClass(new SomeParamType())
{}
3 in C++03, use a default argument (which is ugly):
DerrivedClass::DerrivedClass(SomeParamType* p = new SomeParamType())
: BaseClass(p),
derrivedClassMember(p),
{
...
}
4 Another workaround, to get rid of the constructor default argument in C++03, would be to use multiple inheritance to get the derivedclassMember initialized before the base class:
struct DerivedClassInitializationWorkaround {
SomeParamType* derivedClassMember:
DerivedClassInitializationWorkaround(SomeParamType* param)
: derivedClassMember(param) {}
};
class DerivedClass : private DerivedClassInitializationWorkaround, //this has to go first!
public BaseClass {
public:
DerivedClass::DerivedClass()
: DerivedClassInitializationWorkaround(new SomeParamType())
, BaseClass(derivedClassMember)
{}
};
The initialization of base classes occurs in the order of their declaration, so if you derive from DerivedClassInitializationWorkaround, the derivedClassMember it contains gets initialized first.
In any cases, your code is not exception safe. You should not store owning pointers as raw pointers but use smart pointers. Since you can't change the base class, you will have to determine if it takes ownership of the object (i.e. if it destroys the object you pass to its constructor.
If the base class object takes ownership, you are more or less stuck with the existing solutions, except that your derived class should store a reference instead of the pointer, because the base class object and therfore the SomeParamType object will outlive the derived class' object.
If the base class does not take ownership, you should store a unique_ptr:
class DerivedClass : public BaseClass {
unique_ptr<SomeParamType> derivedClassMember;
DerivedClass::DerivedClass(unique_ptr<SomeParamType> param)
: BaseClass(param.get())
, derivedClassMember(move(param))
{}
public:
DerivedClass::DerivedClass()
: DerivedClass(make_unique<SomeParamType>)
{}
};
Short answer is no, it is not valid.
Here's a good answer to your question:
Order of calling base class constructor from derived class initialization list
Approach 1: Initialise through constructor of dervive class
class base {
protected:
int no;
public:
void showData() {
cout << no;
}
};
class der : public base {
public:
der(int _no) {
no = _no;
}
};
Approach 2: Initialise through constructor of base class
class base {
int no;
protected:
base(int _no) : no(_no){}
public:
void showData() {
cout << no;
}
};
class der : public base {
public:
der(int _no) : base(_no) {
}
};
client code:
der d(10);
d.showData();
Please let me know If there is other method
You should use the second approach, with one reason: if the base class member is private, approach one won't work. It's also strange to see a derived class initializing things that don't belong to it.
Each class ctor should initialise fields in that class. So the second variant.
Obviously the second option for various reasons:
Let constructor of a class do its task: Construction. Let every class initialize its own data members.
Data members may be private, and derived class may not have access to.
Option 1 would involve code maintenance for ALL derived classes, and this would definitely lead to bugs.
Option 1 is not good appraoch as far as encapulation is concerned.
I'd strongly opt for approach 2, as the constructor may also be more complex than just initializing variables. Additionally, private members in case cannot be set in der.
The second is the correct approach. It's always best to initialize with a constructor, that's what they are for. What would you do if you had more than one derived class? What if you wanted to create base class objects by themselves? Put the initalization code in the constructor, that's how C++ is designed to work.
Always use the ctor-initializer to initialize things. Because this is the only place where you can really initialize things. Writing no=no_ anywhere will assign to an already initialized variable. For UDTs this might be a big difference, for references this is not even possible, you always have to initialize them.
So also for uniformity, use the ctor-initalizer everywhere.
I'm looking for a clean C++ idiom for the following situation:
class SomeLibraryClass {
public:
SomeLibraryClass() { /* start initialization */ }
void addFoo() { /* we are a collection of foos */ }
void funcToCallAfterAllAddFoos() { /* Making sure this is called is the issue */ }
};
class SomeUserClass : public SomeLibraryClass {
public:
SomeUserClass() {
addFoo();
addFoo();
addFoo(); // SomeUserClass has three foos.
}
};
class SomeUserDerrivedClass : public SomeUserClass {
public:
SomeUserDerrivedClass() {
addFoo(); // This one has four foos.
}
};
So, what I really want is for SomeLibraryClass to enforce the calling of funcToCallAfterAllAddFoos at the end of the construction process. The user can't put it at the end of SomeUserClass::SomeUserClass(), that would mess up SomeUserDerrivedClass. If he puts it at the end of SomeUserDerrivedClass, then it never gets called for SomeUserClass.
To further clarify what I need, imagine that /* start initialization */ acquires a lock, and funcToCallAfterAllAddFoos() releases a lock.
The compiler knows when all the initializations for an object are done, but can I get at that information by some nice trick?
I would probably implement this with a factory of some sort. The following code should be read as pseudocode, I haven't tried compiling it or anything.
class LibraryClass
{
public:
template<typename D>
static D *GetNewInstance()
{
// by assigning the new D to a LibraryClass pointer, you guarantee it derives from LibraryClass at compile time
// that way, the user can't accidentally type "LibraryClass::GetNewInstance<int>()" and have it work
LibraryClass *c = new D();
c->funcToCallAfterAllAddFoos();
return c;
}
...
};
I'm not sure this is possible. However, you could redesign this a little bit: give your base class constructor an argument std::vector<Foo> const &foosToBeAdded, and let derived classes pass the correct foos:
class SomeLibraryClass {
public:
SomeLibraryClass(std::vector<Foo> const &foosToBeAdded) {
/* start initialization */
std::for_each(foosToBeAdded.begin(), foosToBeAdded.end(),
std::bind1st(std::mem_fun(&SomeLibraryClass::addFoo), this));
funcToCallAfterAllAddFoos();
}
private:
void addFoo(Foo const &someFoo) { /* we are a collection of foos */ }
void funcToCallAfterAllAddFoos() { /* this is now called at the right time */ }
};
class SomeUserClass : public SomeLibraryClass {
public:
SomeUserClass() :
SomeLibraryClass(makeAFooVector())
{
}
private:
std::vector<Foo> makeAFooVector() { /* return a vector with three Foos */ }
};
The pattern can be extended by letting the SomeUserClass constructor also receive a vector of Foos. It would then add its own Foos to the list before calling the base class constructor.
You could also pass iterators instead of vectors. Left as an exercise.
As C++ does not allow reflection, no, you cannot directly obtain this information. (Though there may be some way I'm unaware of to prevent compilation from succeeding)
However, I question the design here. Wouldn't it make more sense to release the lock once SomeLibraryClass is done? If you're concerned about the efficiency of calling AddFoo multiple times your library can provide a member accepting a std::vector<Foo> which would only have to acquire and release the lock once.
Try the Non-virtual Interface Idiom. Make your public method non-virtual, but have it call a private virtual method. The derived classes override this private virtual method (yes, derived classes can override private virtuals). Put the lock stuff in the public non-virtual method around the call to the private virtual method.
EDIT:
After looking at the code more carefully, I think you might be better off having a constructor in the base class that accepts a container of Foo objects and adds them.
Why provide a public addfoo method at all? You say it is all initialization, so let the collection get paassed to the constructor.
Then you can call the nonvirtual functocall from the constructor