Re: own initialization before calling parent's constructor
On Dec 8, 10:40 am, avasilev <alxvasi...@gmail.com> wrote:
Hi Kevin,
Thanks for the detailed response.
Then your code is simply not going to work. That's just how the
language is. The derived class instance (and any non-static members
of it) does not yet exist at the time the base class constructor is
invoked
I think that says it all! That was also my doubt, and the reason to
ask.
You have a few alternatives for a work around, all of which have their
ups and downs:
1) Use a static member function of the derived class for the
calculation
This will not do - actually my purpose is to cache the result from the
calculation for later reuse, but in an initializer list I can't have
local variables, this is why I wanted to use a member variable for
this purpose.
It *is* cached and can be re-used later. In the #1 replacement design
I suggested, it is cached into Base::b, which you had as public so it
can be accessed by any member function of Derived (or anything else
for that matter), including within the initialization list of the
Derived constructor:
class Derived: public Base
{
int d, cachedResult;
static int calculateValueFrom(int arg) { return arg+5; }
public:
int calculateValue() { return calculateValueFrom(d); }
Derived(int arg):
Base(calculateValueFrom(arg)),
d(arg),
cachedResult(Base::b) { }
};
If Base::b is actually private and for some reason you can't modify
the definition of Base to add an accessor for b, then you can
interpose another class Intermediate between Base and Derived in the
inheritance hierarchy, pass the result of (static)
Derived::calculateValueFrom(int) into the Intermediate constructor,
which stores it there, and have that constructor pass its argument
along into the Base constructor. Then Derived can access the cached
value from Intermediate (this is less than ideal as now you have two
copies of the cached value, of course, one in each parent class --
hope they don't get out of sync).
[On refresh, I think this is also what Gert-Jan suggested.]
From your other post:
On Dec 8, 11:34 am, avasilev <alxvasi...@gmail.com> wrote:
: d(calculatedValue)
, Base(calculatedValue)
{
}
And then we are where we started - initializing derived member d,
before calling base constructor :)
No. The order in which objects are initialized before the ctor body
is reached is dependent upon the class declaration, and NOT upon the
order in which they are written in the ctor initializer list: that
order is simply ignored. In the code above, Base's ctor will still be
called before Derived::d is initialized.
It is true that g++ -Wall will warn about the order of the initializer
list above not being consistent with the actual order of
initialization. But in this case it does not matter anyway since
there is no longer a dependency of Base on d nor vice versa. It would
be nice if g++ were smart enough not to display that warning unless it
would actually make a difference, but I suppose that's a hard problem
in general due to possible side effects of ctor arguments.
- Kevin B. McCarty