By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
457,975 Members | 1,172 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 457,975 IT Pros & Developers. It's quick & easy.

Constructor Initialization

P: n/a
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

Jul 19 '05 #1
Share this Question
Share on Google+
5 Replies


P: n/a

"Michael McKnerney" <mi***************@baesystems.com> wrote in message news:3E***************@baesystems.com...
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.
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.
main()
{


You must provide an int return here (even in C these days).
Jul 19 '05 #2

P: n/a
On Fri, 27 Jun 2003 17:39:03 +0000, Michael McKnerney wrote:
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.

[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.


Jul 19 '05 #3

P: n/a


Dhruv wrote:
On Fri, 27 Jun 2003 17:39:03 +0000, Michael McKnerney wrote:
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. [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.


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


HTH,
-Dhruv.


Jul 19 '05 #4

P: n/a

"Michael McKnerney" <mi***************@baesystems.com> wrote in message news:3E**************@baesystems.com...
But wait a minute, if I remove the explicit initialization of A in C's
constructor list, A will get initialized by B.


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.
Jul 19 '05 #5

P: n/a
Michael McKnerney wrote:

Dhruv wrote:

On Fri, 27 Jun 2003 17:39:03 +0000, Michael McKnerney wrote:

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.


[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.


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


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_link5809{at}now.here.com
Jul 19 '05 #6

This discussion thread is closed

Replies have been disabled for this discussion.