own initialization before calling parent's constructor

Discussion in 'C++' started by avasilev, Dec 8, 2011.

  1. avasilev

    avasilev Guest

    Hello,
    The subject says it - is it legal to initialize fields of the derived
    before calling the parent's consctructor, in the initialization list.
    For example:

    class Base
    {
    public:
    int b;
    B(int arg):b(arg){};
    };

    class Derived: public Base
    {
    int d;
    int calculateValue() {return d+5};
    Derived(int arg):
    d(arg), B(calculateValue()){};
    };

    Greetings
    Alex
    avasilev, Dec 8, 2011
    #1
    1. Advertising

  2. On 12/8/2011 8:07 AM, avasilev wrote:
    > The subject says it - is it legal to initialize fields of the derived
    > before calling the parent's consctructor, in the initialization list.


    What's the "parent"? A base class subobject?

    > For example:
    >
    > class Base
    > {
    > public:
    > int b;
    > B(int arg):b(arg){};
    > };
    >
    > class Derived: public Base
    > {
    > int d;
    > int calculateValue() {return d+5};
    > Derived(int arg):
    > d(arg), B(calculateValue()){};


    It's totally legal to write the code like that. It's not going to work
    as you expect, though. First, the base class subobjects are initialized
    in the order of their declaration, then the data members, *in the order
    they are declared*. Of course, calling a member function with 'd'
    uninitialized will have undefined behavior... But it's totally legal.

    > };
    >
    > Greetings
    > Alex


    V
    --
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Dec 8, 2011
    #2
    1. Advertising

  3. avasilev Wrote:

    > Hello,
    > The subject says it - is it legal to initialize fields of the derived
    > before calling the parent's consctructor, in the initialization list.


    It is immaterial if it is legal or nor, because it is impossible.
    The order of initialisation of a class's base-classes and members is not
    dependent on the order they are specified in in the initializer-list, but
    rather the order they are declared in in the class's definition.

    If you compile your example with g++, with the warning flags -Wreorder or
    -Wall, then g++ will complain that the initialization order is different
    from the order in your initializer list.

    > Greetings
    > Alex


    Bart v Ingen Schenau
    Bart v Ingen Schenau, Dec 8, 2011
    #3
  4. avasilev

    avasilev Guest

    On Dec 8, 5:09 pm, Bart v Ingen Schenau <> wrote:
    > avasilev Wrote:
    >
    > > Hello,
    > > The subject says it - is it legal to initialize fields of the derived
    > > before calling the parent's consctructor, in the initialization list.

    >
    > It is immaterial if it is legal or nor, because it is impossible.
    > The order of initialisation of a class's base-classes and members is not
    > dependent on the order they are specified in in the initializer-list, but
    > rather the order they are declared in in the class's definition.
    >
    > If you compile your example with g++, with the warning flags -Wreorder or
    > -Wall, then g++ will complain that the initialization order is different
    > from the order in your initializer list.

    Yes, you are right about the warning. AFAIK, it is there to prevent
    initializing mutually-dependent members which are not initialized in
    the sequence specified in the class declaration.
    In my case, however, I don't have such a dependency. In fact, I have a
    reverse dependency - the call to the base constructor depends on some
    derived-class members being initialized already. Of course the abse
    constructor itself will never depend on derived class members, but
    here I'm talking about constructor arguments (see example).

    Alex

    >
    > > Greetings
    > > Alex

    >
    > Bart v Ingen Schenau
    avasilev, Dec 8, 2011
    #4
  5. avasilev

    avasilev Guest

    On Dec 8, 4:03 pm, Victor Bazarov <> wrote:
    > On 12/8/2011 8:07 AM, avasilev wrote:
    >
    > > The subject says it - is it legal to initialize fields of the derived
    > > before calling the parent's consctructor, in the initialization list.

    >
    > What's the "parent"?  A base class subobject?
    >
    > > For example:

    >
    > > class Base
    > > {
    > > public:
    > >     int b;
    > >     B(int arg):b(arg){};
    > > };

    >
    > > class Derived: public Base
    > > {
    > >    int d;
    > >    int calculateValue() {return d+5};
    > >    Derived(int arg):
    > >      d(arg), B(calculateValue()){};

    >
    > It's totally legal to write the code like that.  It's not going to work
    > as you expect, though.  First, the base class subobjects are initialized
    > in the order of their declaration, then the data members, *in the order
    > they are declared*.  Of course, calling a member function with 'd'
    > uninitialized will have undefined behavior...


    But I'm not doing this. My problem is that i need some derived-class
    members initialized, in order to calculate the argument of the base's
    constructor.

    Alex
    avasilev, Dec 8, 2011
    #5
  6. On 12/8/2011 11:12 AM, avasilev wrote:
    > On Dec 8, 4:03 pm, Victor Bazarov<> wrote:
    >> On 12/8/2011 8:07 AM, avasilev wrote:
    >>
    >>> The subject says it - is it legal to initialize fields of the derived
    >>> before calling the parent's consctructor, in the initialization list.

    >>
    >> What's the "parent"? A base class subobject?
    >>
    >>> For example:

    >>
    >>> class Base
    >>> {
    >>> public:
    >>> int b;
    >>> B(int arg):b(arg){};
    >>> };

    >>
    >>> class Derived: public Base
    >>> {
    >>> int d;
    >>> int calculateValue() {return d+5};
    >>> Derived(int arg):
    >>> d(arg), B(calculateValue()){};

    >>
    >> It's totally legal to write the code like that. It's not going to work
    >> as you expect, though. First, the base class subobjects are initialized
    >> in the order of their declaration, then the data members, *in the order
    >> they are declared*. Of course, calling a member function with 'd'
    >> uninitialized will have undefined behavior...

    >
    > But I'm not doing this. My problem is that i need some derived-class
    > members initialized, in order to calculate the argument of the base's
    > constructor.


    Wrong. You don't need the data member initialized. If you think you
    do, you're either don't understand the meaning of your base class and
    its function, or your design is wrong. Generally speaking, what you
    need is one place from which both the initialization of the base class
    subobject will get its argument *and* the data member is going to be
    initialized. For instance:

    class Derived : public Base
    {
    static int calculateValue(int arg) { return arg+5; }
    Derived(int arg) : Base(calculateValue(arg)), d(arg) {}
    ...

    V
    --
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Dec 8, 2011
    #6
  7. On 12/8/2011 11:10 AM, avasilev wrote:
    > On Dec 8, 5:09 pm, Bart v Ingen Schenau<> wrote:
    >> avasilev Wrote:
    >>
    >>> Hello,
    >>> The subject says it - is it legal to initialize fields of the derived
    >>> before calling the parent's consctructor, in the initialization list.

    >>
    >> It is immaterial if it is legal or nor, because it is impossible.
    >> The order of initialisation of a class's base-classes and members is not
    >> dependent on the order they are specified in in the initializer-list, but
    >> rather the order they are declared in in the class's definition.
    >>
    >> If you compile your example with g++, with the warning flags -Wreorder or
    >> -Wall, then g++ will complain that the initialization order is different
    >> from the order in your initializer list.

    > Yes, you are right about the warning. AFAIK, it is there to prevent
    > initializing mutually-dependent members which are not initialized in
    > the sequence specified in the class declaration.
    > In my case, however, I don't have such a dependency. In fact, I have a
    > reverse dependency - the call to the base constructor depends on some
    > derived-class members being initialized already. Of course the abse
    > constructor itself will never depend on derived class members, but
    > here I'm talking about constructor arguments (see example).


    Either there *is* no such dependency (IOW, you are just *imagining* it)
    or you introduced that dependency because your model is incorrect. Fix
    your model or implement the dependency differently.

    V
    --
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Dec 8, 2011
    #7
  8. On Dec 8, 8:10 am, avasilev <> wrote:
    > On Dec 8, 5:09 pm, Bart v Ingen Schenau <> wrote:
    > > If you compile your example with g++, with the warning flags -Wreorder or
    > > -Wall, then g++ will complain that the initialization order is different
    > > from the order in your initializer list.

    >
    > Yes, you are right about the warning. AFAIK, it is there to prevent
    > initializing mutually-dependent members which are not initialized in
    > the sequence specified in the class declaration.


    Realize that the base class (or classes) is also in some respects a
    member of the derived class, and is always initialized (including, per
    12.6.2 of C++ 2003 standard, the evaluation of any of its constructor
    arguments) before any other members of the derived class.


    > In my case, however, I don't have such a dependency. In fact, I have a
    > reverse dependency - the call to the base constructor depends on some
    > derived-class members being initialized already. Of course the abse
    > constructor itself will never depend on derived class members, but
    > here I'm talking about constructor arguments (see example).


    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 and an attempt is made to evaluate Derived::calculateValue().
    It will quite possibly return garbage. If you are very unlucky, it
    will work by accident until you upgrade to a new compiler version or
    change platforms or something.

    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

    class Base
    {
    public:
    int b;

    // your constructor was misnamed "B"
    Base(int arg):b(arg){}
    };

    class Derived: public Base
    {
    int d;

    // added static function
    static int calculateValueFrom(int arg) { return arg+5; }

    // you probably want ctor and calc fn to be public
    public:

    // rewrite non-static in terms of static to avoid redundancy
    int calculateValue() { return calculateValueFrom(d); }

    Derived(int arg):
    Base(calculateValueFrom(arg)), d(arg) { }
    };



    2) Use two-phase initialization for the base object

    class Base
    {
    public:
    int b;

    // added default ctor
    Base() : b(0) { }

    Base(int arg):b(arg){}

    protected:
    // added setter for b
    void setB(int arg) { b = arg; }
    };

    class Derived: public Base
    {
    int d;

    // again, added public keyword here
    public:

    int calculateValue() {return d+5;}

    Derived(int arg):
    Base(), // not actually needed, used by default
    d(arg)
    { setB(calculateValue()); } // 2-phase init
    };


    3) Multiple inheritance: move the calculation logic into another base
    class, and rely on the fact that base class constructors are called in
    the order in which they are inherited from.

    // Calculation logic moved here
    class Calculator
    {
    protected: // presuming Derived needs access
    int d;

    public:
    int calculateValue() {return d+5;}

    Calculator(int arg) : d(arg) { }
    };

    class Base
    {
    public:
    int b;
    Base(int arg):b(arg){}
    };

    class Derived:
    public Calculator, public Base // must have this order
    {
    public:
    Derived(int arg):
    Calculator(arg),
    // C++03 std 12.6.2 ensures that Calculator is
    // constructed when calculateValue() is called:
    Base(calculateValue()) { }
    };

    - Kevin B. McCarty
    Kevin McCarty, Dec 8, 2011
    #8
  9. avasilev

    avasilev Guest

    > Either there *is* no such dependency (IOW, you are just *imagining* it)
    > or you introduced that dependency because your model is incorrect.  Fix
    > your model or implement the dependency differently.
    >


    The reason I am resorting to this, is actually because I would like to
    do some caching of calculated result, which I then use to pass to the
    base's constructor, and will use further in the object's lifetime for
    other purposes. Normally I would store the result in a variable, and
    not initialize any members, but given the limited syntax of
    initializer lists, I cannot implement logic that I would do normal
    code. Let me clarify with another example:

    struct Base
    {
    Base(int v) {...};
    }

    struct Derived: public Base
    {
    int d;
    void veryCostlyCalculation()
    {
    ....
    d = <calculation result>
    }

    Derived()
    :veryCostlyCalculation(), Base(d) {}
    };


    In an initialization list, how can I store the result of
    veryCostlyCalculation() in a local variable, so that I don't use
    members?
    avasilev, Dec 8, 2011
    #9
  10. avasilev

    avasilev Guest

    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.


    > 2) Use two-phase initialization for the base object
    > 3) Multiple inheritance: move the calculation logic into another base
    > class, and rely on the fact that base class constructors are called in
    > the order in which they are inherited from.


    These will technically do the job, but my optimization is too small to
    resort to complicating the design in such ways. I guess I will just
    leave the optimization for later.
    Thanks
    Alex
    avasilev, Dec 8, 2011
    #10
  11. On 12/8/2011 1:22 PM, avasilev wrote:
    >> Either there *is* no such dependency (IOW, you are just *imagining* it)
    >> or you introduced that dependency because your model is incorrect. Fix
    >> your model or implement the dependency differently.
    >>

    >
    > The reason I am resorting to this, is actually because I would like to
    > do some caching of calculated result, which I then use to pass to the
    > base's constructor, and will use further in the object's lifetime for
    > other purposes. Normally I would store the result in a variable, and
    > not initialize any members, but given the limited syntax of
    > initializer lists, I cannot implement logic that I would do normal
    > code. Let me clarify with another example:
    >
    > struct Base
    > {
    > Base(int v) {...};
    > }
    >
    > struct Derived: public Base
    > {
    > int d;
    > void veryCostlyCalculation()
    > {
    > ....
    > d =<calculation result>
    > }
    >
    > Derived()
    > :veryCostlyCalculation(), Base(d) {}
    > };
    >
    >
    > In an initialization list, how can I store the result of
    > veryCostlyCalculation() in a local variable, so that I don't use
    > members?


    Are you joking? Pulling my leg, by any chance? Why can't you just do

    static int veryCostlyCalculation() {
    ...
    return <calculation result>;
    }

    Derived : Base(veryCostlyCalculation()) {}

    ?

    V
    --
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Dec 8, 2011
    #11
  12. On Dec 8, 7:22 pm, avasilev <> wrote:
    > > Either there *is* no such dependency (IOW, you are just *imagining* it)
    > > or you introduced that dependency because your model is incorrect.  Fix
    > > your model or implement the dependency differently.

    >
    > The reason I am resorting to this, is actually because I would like to
    > do some caching of calculated result, which I then use to pass to the
    > base's constructor, and will use further in the object's lifetime for
    > other purposes. Normally I would store the result in a variable, and
    > not initialize any members, but given the limited syntax of
    > initializer lists, I cannot implement logic that I would do normal
    > code. Let me clarify with another example:
    >
    > struct Base
    > {
    >   Base(int v) {...};
    >
    > }
    >
    > struct Derived: public Base
    > {
    >   int d;
    >   void veryCostlyCalculation()
    >   {
    >     ....
    >     d = <calculation result>
    >   }
    >
    >   Derived()
    >   :veryCostlyCalculation(), Base(d) {}
    >
    > };
    >
    > In an initialization list, how can I store the result of
    > veryCostlyCalculation() in a local variable, so that I don't use
    > members?


    This works but isn't pretty:

    #include <iostream>

    struct Base
    {
    Base(int v) : dBase(v) { }

    int dBase;
    };

    struct Derived : public Base
    {
    Derived(int cachedValue = 0) :
    Base(cachedValue = veryCostlyCalculation()),
    dDerived(cachedValue)
    {
    }

    static int veryCostlyCalculation()
    {
    std::cout << "veryCostlyCalculation\n";
    return 12;
    }

    int dDerived;
    };

    int main()
    {
    Derived d;

    std::cout << d.dBase << "\n";
    std::cout << d.dDerived << "\n";
    }

    C++11 supports constructor forwarding. You could have the default
    constructor
    forward to a private constructor with the argument to be calculated
    once like
    this:

    class Derived : public Base
    {
    public:
    Derived() : Derived(veryCostlyCalculation()) { }

    private:
    Derived(int calculatedValue) :
    Base(calculatedValue),
    dDerived(calculatedValue)
    {
    }

    static int veryCostlyCalculation()
    {
    std::cout << "veryCostlyCalculation\n";
    return 12;
    }

    int dDerived;
    };

    And you can simulate constructor forwarding in C++03 by adding an
    extra derived class:

    class DerivedBase : public Base
    {
    public:
    // ...

    protected:
    Derived(int calculatedValue) :
    Base(calculatedValue),
    dDerived(calculatedValue)
    {
    }

    int dDerived;
    };

    class Derived : public DerivedBase
    {
    public:
    Derived() : DerivedBase(veryCostlyCalculation()) { }

    private:
    static int veryCostlyCalculation()
    {
    std::cout << "veryCostlyCalculation\n";
    return 12;
    }
    };

    Hope this helps!

    Gert-Jan
    Gert-Jan de Vos, Dec 8, 2011
    #12
  13. On 12/8/2011 1:40 PM, avasilev 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.
    >
    >
    >> 2) Use two-phase initialization for the base object
    >> 3) Multiple inheritance: move the calculation logic into another base
    >> class, and rely on the fact that base class constructors are called in
    >> the order in which they are inherited from.

    >
    > These will technically do the job, but my optimization is too small to
    > resort to complicating the design in such ways. I guess I will just
    > leave the optimization for later.


    You could also try using the default argument mechanism:

    class Derived : public Base
    {
    ...
    explicit Derived(int a = costlyCalculation()) : Base(a) {}
    };

    V
    --
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Dec 8, 2011
    #13
  14. On 12/8/2011 1:51 PM, Gert-Jan de Vos wrote:
    > On Dec 8, 7:22 pm, avasilev<> wrote:
    >>> Either there *is* no such dependency (IOW, you are just *imagining* it)
    >>> or you introduced that dependency because your model is incorrect. Fix
    >>> your model or implement the dependency differently.

    >>
    >> The reason I am resorting to this, is actually because I would like to
    >> do some caching of calculated result, which I then use to pass to the
    >> base's constructor, and will use further in the object's lifetime for
    >> other purposes. Normally I would store the result in a variable, and
    >> not initialize any members, but given the limited syntax of
    >> initializer lists, I cannot implement logic that I would do normal
    >> code. Let me clarify with another example:
    >>
    >> struct Base
    >> {
    >> Base(int v) {...};
    >>
    >> }
    >>
    >> struct Derived: public Base
    >> {
    >> int d;
    >> void veryCostlyCalculation()
    >> {
    >> ....
    >> d =<calculation result>
    >> }
    >>
    >> Derived()
    >> :veryCostlyCalculation(), Base(d) {}
    >>
    >> };
    >>
    >> In an initialization list, how can I store the result of
    >> veryCostlyCalculation() in a local variable, so that I don't use
    >> members?

    >
    > This works but isn't pretty:
    >
    > #include<iostream>
    >
    > struct Base
    > {
    > Base(int v) : dBase(v) { }
    >
    > int dBase;
    > };
    >
    > struct Derived : public Base
    > {
    > Derived(int cachedValue = 0) :
    > Base(cachedValue = veryCostlyCalculation()),
    > dDerived(cachedValue)
    > {
    > }
    >
    > static int veryCostlyCalculation()
    > {
    > std::cout<< "veryCostlyCalculation\n";
    > return 12;
    > }
    >
    > int dDerived;


    I think the OP has indicated that there is no need in a data member
    here. He was just trying to use it as the temporary storage.

    > };
    >
    > int main()
    > {
    > Derived d;
    >
    > std::cout<< d.dBase<< "\n";
    > std::cout<< d.dDerived<< "\n";
    > }
    >
    > C++11 supports constructor forwarding. You could have the default
    > constructor
    > forward to a private constructor with the argument to be calculated
    > once like
    > this:
    >
    > class Derived : public Base
    > {
    > public:
    > Derived() : Derived(veryCostlyCalculation()) { }
    >
    > private:
    > Derived(int calculatedValue) :
    > Base(calculatedValue),
    > dDerived(calculatedValue)
    > {
    > }
    >
    > static int veryCostlyCalculation()
    > {
    > std::cout<< "veryCostlyCalculation\n";
    > return 12;
    > }
    >
    > int dDerived;
    > };
    >
    > And you can simulate constructor forwarding in C++03 by adding an
    > extra derived class:
    >
    > class DerivedBase : public Base
    > {
    > public:
    > // ...
    >
    > protected:
    > Derived(int calculatedValue) :


    explicit DerivedBase(int calculatedValue) :

    > Base(calculatedValue),
    > dDerived(calculatedValue)
    > {
    > }
    >
    > int dDerived;
    > };
    >
    > class Derived : public DerivedBase
    > {
    > public:
    > Derived() : DerivedBase(veryCostlyCalculation()) { }
    >
    > private:
    > static int veryCostlyCalculation()
    > {
    > std::cout<< "veryCostlyCalculation\n";
    > return 12;
    > }
    > };


    In order to prevent any problems with clients trying to use
    'DerivedBase' class by itself, I'd probably use a private class like this:

    class Base {
    public:
    Base(int);
    };

    class Derived : public Base
    {
    struct Helper {
    Helper(int v) : value(v) {}
    int value;
    };
    public:
    Derived(Helper h = Helper(veryCostlyCalculation())) :
    Base(h.value)
    { }

    static int veryCostlyCalculation();
    };

    int main()
    {
    Derived d;
    }

    V
    --
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Dec 8, 2011
    #14
  15. avasilev

    avasilev Guest

    Hi Gert-Jan,

    > class DerivedBase : public Base
    > {
    > public:
    >     // ...
    >
    > protected:
    >     Derived(int calculatedValue) :
    >         Base(calculatedValue),
    >         dDerived(calculatedValue)
    >     {
    >     }
    >
    >     int dDerived;
    >
    > };
    >
    > class Derived : public DerivedBase
    > {
    > public:
    >     Derived() : DerivedBase(veryCostlyCalculation()) { }
    >
    > private:
    >     static int veryCostlyCalculation()
    >     {
    >         std::cout << "veryCostlyCalculation\n";
    >         return 12;
    >     }
    >
    > };
    >

    I think this is the most elegant way to do it, at least in my case I
    will use this approach.
    Thanks a lot
    Alex
    avasilev, Dec 8, 2011
    #15
  16. avasilev

    Goran Guest

    On Dec 8, 7:22 pm, avasilev <> wrote:
    > > Either there *is* no such dependency (IOW, you are just *imagining* it)
    > > or you introduced that dependency because your model is incorrect.  Fix
    > > your model or implement the dependency differently.

    >
    > The reason I am resorting to this, is actually because I would like to
    > do some caching of calculated result, which I then use to pass to the
    > base's constructor, and will use further in the object's lifetime for
    > other purposes. Normally I would store the result in a variable, and
    > not initialize any members, but given the limited syntax of
    > initializer lists, I cannot implement logic that I would do normal
    > code. Let me clarify with another example:
    >
    > struct Base
    > {
    >   Base(int v) {...};
    >
    > }
    >
    > struct Derived: public Base
    > {
    >   int d;
    >   void veryCostlyCalculation()
    >   {
    >     ....
    >     d = <calculation result>
    >   }
    >
    >   Derived()
    >   :veryCostlyCalculation(), Base(d) {}
    >
    > };
    >
    > In an initialization list, how can I store the result of
    > veryCostlyCalculation() in a local variable, so that I don't use
    > members?


    Really, is this a joke? Just calculate your value before going to a
    constructor. It then becomes

    Derived(int calculatedValue)
    : d(calculatedValue)
    , Base(calculatedValue)
    {
    }

    If you don't want to expose veryCostlyCalculation to outside world,
    you can do:

    class Derived
    {
    public:
    static Derived Create()
    {
    return Derived(veryCostlyCalculation());
    }
    private:
    Derived(int calculatedValue)
    {
    : d(calculatedValue)
    , Base(calculatedValue)
    }
    }

    Your veryCostlyCalculation makes no sense, because you want to call it
    before you have a constructed members, so you can't access them. If
    so, it can only be static, and even that is dubious. Further, if Base
    holds calculatedValue already, why can't Derived use that!?

    Goran.
    Goran, Dec 8, 2011
    #16
  17. avasilev

    avasilev Guest

    > Really, is this a joke? Just calculate your value before going to a
    > constructor. It then becomes
    >
    > Derived(int calculatedValue)

    calculatedValue is an internal stuff that does not concern the outer
    world, so passing as constructor argument is out of the question.
    > : d(calculatedValue)
    > , Base(calculatedValue)
    > {
    >
    > }


    And then we are where we started - initializing derived member d,
    before calling base constructor :)
    avasilev, Dec 8, 2011
    #17
  18. On 12/8/2011 2:34 PM, avasilev wrote:
    >> Really, is this a joke? Just calculate your value before going to a
    >> constructor. It then becomes
    >>
    >> Derived(int calculatedValue)

    > calculatedValue is an internal stuff that does not concern the outer
    > world, so passing as constructor argument is out of the question.
    >> : d(calculatedValue)
    >> , Base(calculatedValue)
    >> {
    >>
    >> }

    >
    > And then we are where we started - initializing derived member d,
    > before calling base constructor :)


    No. 'Base' is initialized first. Then 'd'. The initialization of
    'Base' does not depend on 'd' having the "correct" value.

    V
    --
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Dec 8, 2011
    #18
  19. On Dec 8, 10:40 am, avasilev <> 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 <> 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
    Kevin McCarty, Dec 8, 2011
    #19
  20. avasilev

    Joe keane Guest

    In article <>,
    avasilev <> wrote:
    >In fact, I have a
    >reverse dependency - the call to the base constructor depends on some
    >derived-class members being initialized already.


    There is some case where the default language init just does -not-
    work for you.

    Better to make an 'uninit' constructor
    and do it step-by-step.

    If you try to use the C++ stuff
    when it doesn't fit, you're just stabbing yourself.

    [i don't know it reflects a design flaw,
    IMHE this problem comes up with classes that otherwise seem to be fine]
    Joe keane, Dec 8, 2011
    #20
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ryan Ternier
    Replies:
    4
    Views:
    3,955
    Cowboy \(Gregory A. Beamer\) [MVP]
    Jul 29, 2004
  2. pantalaimon
    Replies:
    3
    Views:
    51,031
    John Harrison
    Oct 9, 2004
  3. Vamsi
    Replies:
    3
    Views:
    403
    AbdulMunaf
    Jul 19, 2005
  4. Generic Usenet Account
    Replies:
    10
    Views:
    2,198
  5. balaji
    Replies:
    3
    Views:
    923
    Jens Thoms Toerring
    Aug 10, 2011
Loading...

Share This Page