Constructor Initialization

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Michael McKnerney

    Constructor Initialization

    Hi,

    It seems I can influence how a base class is initialized beyond the
    'normal' manner and I was wondering if someone can tell me why this.
    Here's my example.

    class A
    {
    public:
    A(int a=1, int b=1, int c=1) : _a(a), _b(b), _c(c) {}
    void print()
    { cout << _a << "," << _b << "," << _c << endl; }
    private:
    int _a, _b, _c;
    };

    class B : public virtual A
    {
    public:
    B(int a=1, int b=1, int c=1) : A(a, b, c) {}
    };

    class C : public virtual B
    {
    public:
    C(int a=1, int b=1, int c=1)
    :
    B(a, b, c),
    A(2,2,2) // I can explicitly initialize A here and override
    the default values
    {}
    };

    main()
    {
    C c;
    c.print();
    }


    thanks,
    Mike

  • Ron Natalie

    #2
    Re: Constructor Initialization


    "Michael McKnerney" <michael.mckner ney@baesystems. com> wrote in message news:3EFC871D.5 C0DDEDB@baesyst ems.com...[color=blue]
    > Hi,
    >
    > It seems I can influence how a base class is initialized beyond the
    > 'normal' manner and I was wondering if someone can tell me why this.[/color]

    Because you have virtual base classes. The most derived class must initialize
    all the virtual bases. The initialization of A specified in the B constructor has no
    bearing on the creation of C objects.
    [color=blue]
    > main()
    > {[/color]

    You must provide an int return here (even in C these days).


    Comment

    • Dhruv

      #3
      Re: Constructor Initialization

      On Fri, 27 Jun 2003 17:39:03 +0000, Michael McKnerney wrote:
      [color=blue]
      > Hi,
      >
      > It seems I can influence how a base class is initialized beyond the
      > 'normal' manner and I was wondering if someone can tell me why this.
      > Here's my example.[/color]
      [snip]......


      For virtual bases, the rule is different. The most derived class is
      responsible for constructing the virtual base class, as opposed to its
      immediate descendant in case of non-virtual bases.

      HTH,
      -Dhruv.






      Comment

      • Michael McKnerney

        #4
        Re: Constructor Initialization



        Dhruv wrote:
        [color=blue]
        > On Fri, 27 Jun 2003 17:39:03 +0000, Michael McKnerney wrote:
        >[color=green]
        > > Hi,
        > >
        > > It seems I can influence how a base class is initialized beyond the
        > > 'normal' manner and I was wondering if someone can tell me why this.
        > > Here's my example.[/color]
        > [snip]......
        >
        > For virtual bases, the rule is different. The most derived class is
        > responsible for constructing the virtual base class, as opposed to its
        > immediate descendant in case of non-virtual bases.
        >[/color]

        But wait a minute, if I remove the explicit initialization of A in C's
        constructor list, A will get initialized by B.

        [color=blue]
        >
        > HTH,
        > -Dhruv.[/color]

        Comment

        • Ron Natalie

          #5
          Re: Constructor Initialization


          "Michael McKnerney" <michael.mckner ney@baesystems. com> wrote in message news:3EFC8DD8.B 48769B@baesyste ms.com...
          [color=blue]
          > But wait a minute, if I remove the explicit initialization of A in C's
          > constructor list, A will get initialized by B.[/color]

          No it will not. If you remove the explicit initialization, it will invoke the
          default constructor. If A didn't have a default constructor, then you'd
          get an error.


          Comment

          • Jim Fischer

            #6
            Re: Constructor Initialization

            Michael McKnerney wrote:[color=blue]
            >
            > Dhruv wrote:
            >
            >[color=green]
            >>On Fri, 27 Jun 2003 17:39:03 +0000, Michael McKnerney wrote:
            >>
            >>[color=darkred]
            >>>Hi,
            >>>
            >>>It seems I can influence how a base class is initialized beyond the
            >>>'normal' manner and I was wondering if someone can tell me why this.
            >>>Here's my example.[/color]
            >>
            >>[snip]......
            >>
            >>For virtual bases, the rule is different. The most derived class is
            >>responsible for constructing the virtual base class, as opposed to its
            >>immediate descendant in case of non-virtual bases.[/color]
            >
            > But wait a minute, if I remove the explicit initialization of A in C's
            > constructor list, A will get initialized by B.[/color]

            Nope. If you remove the explicit initialization of A in C's initializer
            list and then invoke the class C ctor,

            C(int a=1, int b=1, int c=1)
            : B(a,b,c)
            { }

            the sequence of events (IIRC) is this:

            1) Program invokes the C ctor
            2) The C ctor implicitly invokes A's default ctor
            3) The C ctor invokes 'B(a,b,c)' as specified in the initializer list of
            the class C ctor. The B ctor does not invoke the A ctor.

            So the class C ctor -- not the B ctor -- is still the entity that
            invokes the class A ctor.


            FWIW, if you rewrite your code a bit, this sequence of events will (IMO)
            be easier to observe.

            <example>
            <code>

            #include <iostream>
            using namespace std;

            class A {
            public:
            A(int a=1, int b=1, int c=1)
            : a_(a), b_(b), c_(c)
            { cout << "A(" << a << ',' << b << ',' << c << ")\n"; }

            void print()
            { cout << a_ << ',' << b_ << ',' << c_ << '\n'; }

            private:
            int a_, b_, c_;
            };

            class B : public virtual A {
            public:
            B(int a=2, int b=2, int c=2)
            : A(a, b, c)
            { cout << "B(" << a << ',' << b << ',' << c << ")\n"; }
            };

            class C : public virtual B {
            public:
            C(int a=3, int b=3, int c=3)
            // : A(4,4,4), B(a,b,c)
            : B(a,b,c)
            { }
            };

            int main()
            {
            C c;
            c.print();
            }

            </code>

            <output>
            A(1,1,1)
            B(3,3,3)
            1,1,1
            </output>

            </example>


            Some side notes:

            1) DO NOT use variable names that start with a leading underscore, e.g.,
            '_a'. These names (and some others) are reserved for the
            implementation' s use -- e.g., the standard library, compiler-specific
            language extensions, the OS's API, etc. So if you want to use
            underscores to denote variable names, place the underscore at the end of
            the name, 'a_', and not at the beginning.

            2) In this code sample, class A's ctor is *always* invoked before class
            B's ctor. This sequence holds even if you try (futilely) to specify the
            base class ctor invocation sequence as B first, then A, in the class C
            ctor initializer list:

            C() : B(), A() { }

            IOW, the compiler ignores the B,A sequence specified above, and
            implicitly implements C's initializer list as A,B, i.e.,

            C() : A(), B() { }

            [n.b. Most compilers are nice enough to warn you when they implicitly
            reorder the initializer list's arguments like this.]

            --
            Jim

            To reply by email, remove "link" and change "now.here" to "yahoo"
            jfischer_link58 09{at}now.here. com


            Comment

            Working...