Limitations of initialization list

M

Marcin Kalicinski

Hi,

Constructor of derived class needs to do some complex things before it calls
base class constructor. There is an ugly solution:

bool ComplexThingToDo()
{
// ...
return false; // dummy
}

class Derived: public Base
{
bool dummy;
public:
Derived(): dummy(ComplexThingToDo()), Base() { }
};

But I'm afraid that sequence of initializers in initialization list does not
enforce the actual sequence of execution. So this ugly solution will not
work. Is there another way? Perhaps it is an example of bad design, doing
some complex things before calling base class constructor?

Best regards,
Marcin
 
V

Victor Bazarov

Marcin said:
Constructor of derived class needs to do some complex things before it calls
base class constructor.

That is not possible.
There is an ugly solution:

It is not a solution.
bool ComplexThingToDo()
{
// ...
return false; // dummy
}

class Derived: public Base
{
bool dummy;
public:
Derived(): dummy(ComplexThingToDo()), Base() { }
};

But I'm afraid that sequence of initializers in initialization list does not
enforce the actual sequence of execution. So this ugly solution will not
work. Is there another way?

Not if you can't change the base class. If you _can_ change the base
class, give your 'Base' class a dummy argument and do

Derived() : Base(ComplexThingToDo()) {}
Perhaps it is an example of bad design, doing
some complex things before calling base class constructor?

Yes, it is. You're trying to call a member function of an object that
hasn't been constructed yet.

Victor
 
M

Marcin Kalicinski

Perhaps it is an example of bad design, doing
Yes, it is. You're trying to call a member function of an object that
hasn't been constructed yet.

Thanks for your reply. But I'm not calling any member, I'm just calling some
standalone function ComplexThingToDo(), which is not a member of Base, or
any other class. For example it might initialize some global I/O system in a
suitable way for the Base class constructor to use.

Marcin
 
P

Phlip

Marcin said:
Constructor of derived class needs to do some complex things before it calls
base class constructor. There is an ugly solution:

bool ComplexThingToDo()
{
// ...
return false; // dummy
}

class Derived: public Base
{
bool dummy;
public:
Derived(): dummy(ComplexThingToDo()), Base() { }
};

But I'm afraid that sequence of initializers in initialization list does not
enforce the actual sequence of execution. So this ugly solution will not
work.

Things (generally) destruct in the reverse order that they construct. Hence
their construction order is (generally) determined. Hence, a class
constructs bases, then members, in the order they appear in source. So when
you write dummy(), Base(), the compiler compiles Base(), dummy().
Is there another way? Perhaps it is an example of bad design, doing
some complex things before calling base class constructor?

Uh, yeah. How about the constructors do nothing, then you call an init()
method that does something?
 
M

Marcin Kalicinski

Is there another way? Perhaps it is an example of bad design, doing
Uh, yeah. How about the constructors do nothing, then you call an init()
method that does something?

I thought about it also, but it seems to me like abandonning nice and safe
element of C++ (the constructor/destructor pair) and going a step backwards
towards C.

Best regards,
Marcin
 
R

Risto Lankinen

Victor Bazarov said:
That is not possible.

. . .
Not if you can't change the base class. If you _can_ change the base
class, give your 'Base' class a dummy argument and do

Derived() : Base(ComplexThingToDo()) {}

You can actually do it even without changing the Base class
using the following... well... ugly trick:

class FixBase
{
friend Derived;
FixBase() { /* do the trick here */ }
};

class Derived : public Base , private virtual FixBase
{
Derived() : Base() { }
};

Then, FixBase::FixBase() will always be called before the
Base::Base() [of the corresponding Derived instance].

- Risto -
 
?

=?ISO-8859-15?Q?Juli=E1n?= Albo

Marcin said:
Constructor of derived class needs to do some complex things before it
calls base class constructor. There is an ugly solution:

bool ComplexThingToDo()
{
// ...
return false; // dummy
}

class Derived: public Base
{
bool dummy;
public:
Derived(): dummy(ComplexThingToDo()), Base() { }
};

But I'm afraid that sequence of initializers in initialization list does
not enforce the actual sequence of execution. So this ugly solution will
not work. Is there another way? Perhaps it is an example of bad design,
doing some complex things before calling base class constructor?

Add another base class.

class ComplexThing {
public:
ComplexThing () { .... }
};

class Derived: public ComplexThing, public Base { ... };
 
V

Victor Bazarov

Marcin said:
Thanks for your reply. But I'm not calling any member, I'm just calling some
standalone function ComplexThingToDo(), which is not a member of Base, or
any other class. For example it might initialize some global I/O system in a
suitable way for the Base class constructor to use.

My mistake. The others who replied suggested to add another base class to
your 'Derived' to specifically initialise something before 'Base', it's
a better solution than changing 'Base' class (that you can't always do).

V
 
C

Chris Theis

Marcin Kalicinski said:
Hi,

Constructor of derived class needs to do some complex things before it calls
base class constructor. There is an ugly solution:

bool ComplexThingToDo()
{
// ...
return false; // dummy
}

class Derived: public Base
{
bool dummy;
public:
Derived(): dummy(ComplexThingToDo()), Base() { }
};

But I'm afraid that sequence of initializers in initialization list does not
enforce the actual sequence of execution. So this ugly solution will not
work. Is there another way? Perhaps it is an example of bad design, doing
some complex things before calling base class constructor?

Best regards,
Marcin

Naturally objects are constructed top to bottom in the inheritance tree.
However, you can enforce a specific order of executed base class ctors by
using multiple and virtual inheritance (see FAQ 25.14). This is a way to
solve your problem but still I have the itching feeling that you might have
a flaw in the design. Why can't the complex things be done by the base class
ctor? If they cannot but it is a problem if they are not yet done when the
base class ctor is executed then you might have a dependency of a base class
to a derived class and this is certainly a flaw. I don't suggest that this
is the case for you but you might consider rethinking your design.

Cheers
Chris
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,042
Latest member
icassiem

Latest Threads

Top