C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Re: Initialization of virtual bases

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Attila Feher
Guest





PostPosted: Tue Aug 26, 2003 6:42 pm    Post subject: Re: Initialization of virtual bases Reply with quote



Dave Theese wrote:
Quote:
Hello all,

The code example below has proper behavior (of course), but I'm
trying to understand how the behavior is brought about.
Specifically, what happens to B's and C's initialization of A??? Is
it just ignored even though it explicitly appears in the code?
[SNIP]


Virtual bases are initialized only once, and by the most derived class type
(the one you actually instantiate). IIRC they *must* be initialized (if
there is no default constructor).

So (while it may not be the right wording) you may say so, that the
initialization done by any base class is ignored.

--
Attila aka WW



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Francis Glassborow
Guest





PostPosted: Tue Aug 26, 2003 6:47 pm    Post subject: Re: Initialization of virtual bases Reply with quote



In article <a1A2b.8257$QT5.3304@fed1read02>, Dave Theese
<cheeser_1998 (AT) yahoo (DOT) com> writes
Quote:
Hello all,

The code example below has proper behavior (of course), but I'm trying to
understand how the behavior is brought about. Specifically, what happens to
B's and C's initialization of A??? Is it just ignored even though it
explicitly appears in the code?

The rule for initilaisation of virtual bases is simple, only the most
derived class does it and all other bases both direct and indirect
simply use the result. It is achieved by the implementation only calling
the virtual base ctor from the most derived class (and before any other
non-virtual base ctors) All other calls to a virtual base ctor are
suppressed.


--
Francis Glassborow ACCU
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Ben Hutchings
Guest





PostPosted: Tue Aug 26, 2003 7:00 pm    Post subject: Re: Initialization of virtual bases Reply with quote



In article <a1A2b.8257$QT5.3304@fed1read02>, Dave Theese wrote:
Quote:
Hello all,

The code example below has proper behavior (of course), but I'm trying
to understand how the behavior is brought about. Specifically, what
happens to B's and C's initialization of A??? Is it just ignored even
though it explicitly appears in the code?
snip


Yes. The selection of constructor and constructor arguments for a
virtual base is always controlled by the complete object's constructor
(even if it implicitly selects a default constructor).

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
llewelly
Guest





PostPosted: Tue Aug 26, 2003 7:05 pm    Post subject: Re: Initialization of virtual bases Reply with quote

"Dave Theese" <cheeser_1998 (AT) yahoo (DOT) com> writes:

Quote:
Hello all,

The code example below has proper behavior (of course), but I'm trying to
understand how the behavior is brought about. Specifically, what happens to
B's and C's initialization of A??? Is it just ignored even though it
explicitly appears in the code?

It is ignored when you create a D. It is used when you create a B or C
which is not a base sub-object of a D.

Quote:

Thanks,
Dave

#include
using namespace std;

class A
{
public:
A(int d): data(d)
{
cout << "data initialized to " << d << endl;
}

private:
int data;
};

class B: virtual public A
{
public:
B(int d): A(d)
{
}
};

class C: virtual public A
{
public:
C(int d): A(d)
{
}
};

class D: public B, public C

Since the A sub-object of both B and C is virtual, D will contain only
1 A sub-object - not two. Since there is only one A sub-object, if
the constructors of B and C were allowed to initialize it, we
would have (potentially dangers) double initialization. So the
initializations of A in B's and C's constructors are ignored when
a D is created, and only the initialization of A in D's
constructor is used. That's also why you get compile-time error if
you don't explicitly initialize the A sub-object from D's
constructor, and don't provide a default constructor for A.

This is covered in TC++PL 3 (or SE) 15.2.4[.1] .

Quote:
{
public:
D(int d): A(d), B(d + 1), C(d + 2)
{
}
};

[snip]


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Dave Theese
Guest





PostPosted: Wed Aug 27, 2003 3:14 pm    Post subject: Re: Initialization of virtual bases Reply with quote

Let me try to refine the discussion at this point...

Given that the virtual base may only be initialized once (since only one
instance of it exists, by definition), I'm curious as to why, syntactically
(even if not in reality), all three of the classes derived from the virtual
base must initialize it. Why force a programmer to show three
initializations of the virtual base given that only one (that of the
most-derived class) is actually used? Seems to make for confusing code...

Perhaps eliminating the superfluous initializations of the virual base would
present parsing / semantic checking difficulties. I mean, you would
normally expect a derived class to explicitily initialize its base if the
base has no default constructor. This is a somewhat unusual case (though
not that unusual), and maybe it would be tough to implement this special
case and have the ability to leave out the unused initializations...

Perhaps that I see errors when I remove the superfluous initializations is
an artifact of my platform (VC++ 7.1). Maybe other compilers would
(correctly) not force me to show the unused initializations. But I doubt
it...


Quote:
Hello all,

The code example below has proper behavior (of course), but I'm trying to
understand how the behavior is brought about. Specifically, what happens
to
B's and C's initialization of A??? Is it just ignored even though it
explicitly appears in the code?

The rule for initilaisation of virtual bases is simple, only the most
derived class does it and all other bases both direct and indirect
simply use the result. It is achieved by the implementation only calling
the virtual base ctor from the most derived class (and before any other
non-virtual base ctors) All other calls to a virtual base ctor are
suppressed.

#include <iostream>

using namespace std;

class A
{
public:
A(int d): data(d)
{
cout << "data initialized to " << d << endl;
}

private:
int data;
};

class B: virtual public A
{
public:
B(int d): A(d)
{
}
};

class C: virtual public A
{
public:
C(int d): A(d)
{
}
};

class D: public B, public C
{
public:
D(int d): A(d), B(d + 1), C(d + 2)
{
}
};

int main(void)
{
// Displays "data initialized to 1"
D foo(1);

return 0;
}


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Stephen Howe
Guest





PostPosted: Thu Aug 28, 2003 10:40 am    Post subject: Re: Initialization of virtual bases Reply with quote

Quote:
Given that the virtual base may only be initialized once (since only one
instance of it exists, by definition), I'm curious as to why,
syntactically
(even if not in reality), all three of the classes derived from the
virtual
base must initialize it.

Well what happens if you wanted

D d(2);
C c(3);
B b(4);

Here because you have B and C object that is not part of D, the A part still
needs initialising.

Stephen Howe




[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
kanze@gabi-soft.fr
Guest





PostPosted: Thu Aug 28, 2003 8:34 pm    Post subject: Re: Initialization of virtual bases Reply with quote

"Dave Theese" <cheeser_1998 (AT) yahoo (DOT) com> wrote

Quote:
Let me try to refine the discussion at this point...

Given that the virtual base may only be initialized once (since only
one instance of it exists, by definition), I'm curious as to why,
syntactically (even if not in reality), all three of the classes
derived from the virtual base must initialize it. Why force a
programmer to show three initializations of the virtual base given
that only one (that of the most-derived class) is actually used?
Seems to make for confusing code...

The problem is that the most derived class may change, and may not be
known to the compiler. Thus, practically speaking, if the virtual base
class has no default constructor, every derived class must contain an
initializer for the virtual base.

This is NOT what the standard says; the standard says only that the most
derived class must provide the initialization. It is, however, what all
compilers that I know of do. In fact, the last time I tried it (some
time ago, I'll admit, and I forget with which compiler), the compiler
required even an abstract derived class (which could never be the most
derived class of an instance) to provide an initializer.

Quote:
Perhaps eliminating the superfluous initializations of the virual base
would present parsing / semantic checking difficulties.

No particular problems for the compiler, but it would change when errors
are detected.

struct VB { VB( int i ) ; } ;
struct L : virtual VB {} ;
struct R : virtual VB {} ;
struct D : L, R {} ;

The compiler cannot know that D is a most derived class (nor that L or R
won't be for some instances). Current implementations generate compile
time errors for all three classes. If the compiler is to forgo the
error in L and R, it must also forgo it in D, since it has no way of
knowing that D will be the end of the inheritance. The earliest that
the compiler could generate an error for D is when we tried to
instantiate it -- L, R, and D will have effectively become abstract
classes.

To tell the truth, I don't know whether the current behavior was more or
less accidental in CFront, and then copied by all later compilers, or
whether it was intentional, and the wording of the standard just doesn't
reflect the intent. Or, which is also quite possible, I have missed
something in the standard, although §12.6.2/8 seems quite clear: the
initialization is ill formed if and only if the constructor of the most
derived class does not specify a mem-initializer, and the virtual base
class does not have an accessible default constructor.

Anyway, as it now stands, the following program is perfectly legal
according to the standard, but neither g++ (3.2.2) nor Sun CC (5.1)
(nor most other compilers, I suspect) accept it:

#include <iostream>
#include <ostream>

struct VB { VB( int i ) ; } ;
struct L : virtual VB {} ;
struct R : virtual VB {} ;
struct D : L, R {} ;
struct E : D { E() : VB( 1 ) {} } ;

VB::VB( int i )
{
std::cout << "VB::VB: " << i << 'n' ;
}

int
main()
{
E anE ;
return 0 ;
}

At any rate, my usual rule is to require a default constructor in all
virtual bases. Most of the time, the virtual base class will be
abstract, will not contain any data, and so will only have a default
constructor, but in the exceptional case, if no default constructor is
reasonable, I will provide one which aborts with an error message --
this allows compiling something like the above, but it does shift the
error detection if I try to instantiate D to runtime.

--
James Kanze GABI Software mailto:kanze (AT) gabi-soft (DOT) fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Francis Glassborow
Guest





PostPosted: Thu Aug 28, 2003 8:36 pm    Post subject: Re: Initialization of virtual bases Reply with quote

In article <3f4cd366$0$246$ed9e5944 (AT) reading (DOT) news.pipex.net>, Stephen
Howe <SPAMstephen.howeGUARD (AT) tnsofres (DOT) com> writes
Quote:
Given that the virtual base may only be initialized once (since only one
instance of it exists, by definition), I'm curious as to why,
syntactically
(even if not in reality), all three of the classes derived from the
virtual
base must initialize it.

Well what happens if you wanted

D d(2);
C c(3);
B b(4);

Here because you have B and C object that is not part of D, the A part still
needs initialising.

In addition, a virtual base that requires explicit initialisation seems
suspect to me. Of course there are exceptions, but in general a virtual
base class should only have a default and possibly a copy ctor. If it
has any other ctor that should (apart from a copy ctor) be its only
ctor. Virtual base classes with multiple ctors are prone to abuse.


--
Francis Glassborow ACCU
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Attila Feher
Guest





PostPosted: Thu Aug 28, 2003 8:39 pm    Post subject: Re: Initialization of virtual bases Reply with quote

Dave Theese wrote:
[SNIP]
Quote:
Perhaps that I see errors when I remove the superfluous
initializations is an artifact of my platform (VC++ 7.1). Maybe
other compilers would (correctly) not force me to show the unused
initializations. But I doubt it...

Unless your base classes (up to the most derived) are all abstract, why
would that initialization be useless? All those base classes _can_ be
instantiated and at that time _they_ will call the virtual bases
constructor.

--
Attila aka WW



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.