Topic: Virtual inheritance & non-default ctors.
Author: "Per Velschow" <per@velschow.com>
Date: 2000/09/16 Raw View
> But as you wrote it, B's ctor will never be called BEFORE A's ctor has
> already been run. So I do not understand what you are getting at. No
> relaxation is needed, the rules for ABC's with virtual bases ensure that
> the virtual base ctor will never be called through that classes ctor; it
> must have already been called by a more derived class.
What I am getting at is this: Why should the compiler force me to write the
call to A below? As I understand it, there is no chance that it will ever
get executed because A's constructor must already have been called by a
derived class.
class B : public virtual A {
public:
B() : A(42) {} // Dummy argument to A.
virtual void method() = 0;
};
Therefore it seems kinda silly that I have to write that call. In the
example below, I just gave a dummy argument to A's constructor since I knew
that it would never be called? Doesn't that seem pretty useless? In fact,
there are even some cases in which coming up with a dummy value is not
possible at all.
/Per
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: 2000/09/15 Raw View
In article <8pm23o$ap6$1@nnrp1.deja.com>, wmm@fastdial.net writes
>That particular use is now no longer needed, but I can still imagine
>operations that are class-specific but should be performed by every
>constructor in a given hierarchy. It's very helpful to have the
>compiler point out places where I might have inadvertently omitted a
>needed initialization.
Yes. I had forgotten that case. So either there should ONLY be a default
ctor, or there must not be one at all.
Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Olaf Krzikalla \(Reico GmbH\)" <Entwicklung@reico.de>
Date: 2000/09/15 Raw View
Hi,
> Unlike Java programmers, I have no problem with an ABC
including data,
> nor do I have a problem with a user written default ctor
(perhaps you
> thought a default ctor was always compiler generated? No,
a default ctor
> is any ctor that can be called without any caller provided
data, if a
> virtual base class includes data I would strongly advocate
that it has a
> user written default ctor unless all the data already have
default ctors
> that initialise them)
That's not the point. I just would like to initialize my
virtual base class data members
like any other class members, which I can't do without
getting mad (as you stated earlier :-).
But thank you for the hint with the ABC, it leads to the
following idea:
class A {
protected:
virtual int& getData() = 0; // functions like this
gives me acess to some shared data members
virtual void f(); // may have a default
implementation
virtual void g(); // may have a default
implementation
};
class data : virtual public A {
// all the data shared members
protected:
virtual int& getData();
data (/*some arguments*/); // sets data members
};
class Baux : virtual public A {
protected:
virtual void f();
};
class Caux : virtual public A {
protected:
virtual void g();
};
class B : public Baux, data { /*ctor*/ };
class C : public Baux, data { /*ctor*/ };
class D : public B, public Caux {} // calls data's c'tor
via B
class D : public C, public Baux {} // calls data's c'tor
via C
This seems to work fine. Gives me control over the
constructor sequence and I don't have to be worry about the
constructor args of data in subclasses of D. The only
problem: I must ensure, that every subclass contains only
one data object. But that's all.
Olaf Krzikalla
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Per Velschow" <per@velschow.com>
Date: 2000/09/15 Raw View
> Being an ABC has nothing to do with whether it has or does not have
> data.
I did not talk about empty classes at all. There is no terminology problem
on my part.
> Now, I have read the above quoted paragraph several times and cannot
> make any sense of it. All bases must have a ctor called, even if it does
> nothing.
I thought it was clear enough, but it may be that I am missing a point on
virtual base classes without default ctors. I have never used this in
practice before. So instead of reiterating my statement, let me show an
example:
class A {
public:
A(int v) : val(v) {
virtual ~A() {}
private:
const int val;
};
class B : public virtual A {
public:
B() : A(42) {} // Dummy argument to A.
virtual void method() = 0;
};
class C : public virtual B {
public:
C(int v) : A(v) {} // Actual argument to A
virtual void method() {}
};
Now, B is an abstract class so it can never be instantiated. Therefore there
is no way that the call to the base constructor A(42) will ever get
executed. Am I right so far?
So what I am saying is that the compiler could choose to relax the
requirement that B's constructor must call A's constructor. Do you agree? If
not, why?
/Per
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: 2000/09/15 Raw View
In article <8pp7sk$bst$1@news.inet.tele.dk>, Per Velschow
<per@velschow.com> writes
>I thought it was clear enough, but it may be that I am missing a point
>on virtual base classes without default ctors. I have never used this in
>practice before. So instead of reiterating my statement, let me show an
>example:
>
>class A {
>public:
> A(int v) : val(v) {
> virtual ~A() {}
>private:
> const int val;
>};
>
>class B : public virtual A {
>public:
> B() : A(42) {} // Dummy argument to A.
> virtual void method() = 0;
>};
>
>class C : public virtual B {
>public:
> C(int v) : A(v) {} // Actual argument to A
> virtual void method() {}
>};
>
>Now, B is an abstract class so it can never be instantiated. Therefore
>there is no way that the call to the base constructor A(42) will ever
>get executed. Am I right so far?
>
>So what I am saying is that the compiler could choose to relax the
>requirement that B's constructor must call A's constructor. Do you
>agree? If not, why?
But as you wrote it, B's ctor will never be called BEFORE A's ctor has
already been run. So I do not understand what you are getting at. No
relaxation is needed, the rules for ABC's with virtual bases ensure that
the virtual base ctor will never be called through that classes ctor; it
must have already been called by a more derived class.
Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: wmm@fastdial.net
Date: Tue, 12 Sep 2000 20:34:33 GMT Raw View
In article <9i56UhAfshv5Ewwj@ntlworld.com>,
Francis Glassborow <francisG@robinton.demon.co.uk> wrote:
> The moral is that a virtual base class should never depend on non-
> default construction. I would go so far as to suggest that a virtual
> base class should never have ctors other than the default and copy
ones.
Actually, I think that the fact that _every_ constructor of
_every_ class must initialize every virtual base class in
its hierarchy directly is sometimes pretty useful. For
instance, in the days before RTTI was added to the language,
I oftentimes would put a "class_name" virtual base add-in
at the root of my hierarchy, with a single constructor that
took a character string argument. This meant that it was
impossible for me to forget to register the class name on
construction, something I often did before this technique
occurred to me.
That particular use is now no longer needed, but I can
still imagine operations that are class-specific
but should be performed by every constructor in a given
hierarchy. It's very helpful to have the compiler point
out places where I might have inadvertently omitted a
needed initialization.
--
William M. Miller, wmm@fastdial.net
Vignette Corporation (www.vignette.com)
Sent via Deja.com http://www.deja.com/
Before you buy.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Per Velschow" <per@velschow.com>
Date: 2000/09/13 Raw View
> But the rules are not arbitrary. ctors have to be called. If your design
> relies on calling a specific non-default ctor for a virtual base it is
> extremely fragile because it can, and probably will be, broken when
> another class using that virtual base is added to the base classes later
> in the process of inheritance.
Is there actually any need to call the ctor of the virtual base in an
abstract class? It seems that it would have no chance of ever getting
called. Thus, you will probably always want to give such a ctor call some
dummy argument which seems a bit silly. Didn't the Standards Committee
consider this optional for abstract classes?
/Per
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: 2000/09/13 Raw View
In article <8pmijc$m05$1@news.inet.tele.dk>, Per Velschow
<per@velschow.com> writes
>Is there actually any need to call the ctor of the virtual base in an
>abstract class? It seems that it would have no chance of ever getting
>called. Thus, you will probably always want to give such a ctor call
>some dummy argument which seems a bit silly. Didn't the Standards
>Committee consider this optional for abstract classes?
I think we are having terminology problems here:
An abstract base class is any class that has at least one pure virtual
function. Those are classes in which a pure virtual function is
explicitly declared, together with classes directly derived from an ABC
in which at least one of the inherited pure virtual functions has not
been defined (implemented).
Being an ABC has nothing to do with whether it has or does not have
data.
Default ctor: any ctor in which all parameters (if any) have default
arguments provided. If there is no user declared ctor the compiler will
generate a default ctor if it can.
Now, I have read the above quoted paragraph several times and cannot
make any sense of it. All bases must have a ctor called, even if it does
nothing.
Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Ron Natalie <ron@sensor.com>
Date: 2000/09/14 Raw View
wmm@fastdial.net wrote:
>
> Actually, I think that the fact that _every_ constructor of
> _every_ class must initialize every virtual base class in
> its hierarchy directly is sometimes pretty useful. For
> instance, in the days before RTTI was added to the language,
> I oftentimes would put a "class_name" virtual base add-in
> at the root of my hierarchy,
We even post-RTTI have done exactly that. The RTTI type names
aren't necessarily human friendly.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Benjamin Scherrey <scherrey@switchco.com>
Date: 08 Sep 00 14:53:11 GMT Raw View
This is a multi-part message in MIME format.
--------------8162A4C40B6C71CE4742AC88
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
I've been trying to implement a dynamic interface/inplementation
mechanism that makes heavy use of templates and virtual inheritance.
Basically it allows you to define a class as an interface and to load
implementations of that interface (i.e. classes that inherit from the
interface class) at runtime.
Presently, however, I'm having fits getting parameters to the
implementation constructors to make it up to the interface instance.
I've attached some sample code that exercises the virtual inheritance
mechanism and, as you can see from the code, instantiating instances X6,
Y3, and Z3 refuse to pass the provided parameter up to the virtual
interface classes constructor.
Unfortunately, I need to be able to have interfaces which don't allow
default constructors. Plus I'm not too sure about the safety of copying
some of these values but, for now, I've narrowed my problem down to this
issue. Is this behavior correct or is my compiler broken (gcc-2.95.2
under x86 linux)?
thanx very much & later,
Ben Scherrey
--------------8162A4C40B6C71CE4742AC88
Content-Type: text/plain; charset=us-ascii;
name="vinherit.cpp"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="vinherit.cpp"
//
// vinherit.cpp - Tests resolution of virtual inheritance.
//
#include <iostream>
#include <string>
class A
{
public:
A( void ) { cout << "A ctor @ " << this << endl; }
A( int ) { cout << "A int ctor @ " << this << endl; }
A( const A& a ) { cout << "A copy ctor @ " << this << " from " << &a << endl; }
virtual ~A( void ) { cout << "A dtor @ " << this << endl; }
virtual void f1( void ) { cout << "A::f1" << endl; }
virtual void f2( void ) = 0;
};
class B : public A
{
public:
B( void ) : A() { cout << "B ctor @ " << this << endl; }
B( int i ) : A( i ) { cout << "B int ctor @ " << this << endl; }
B( const B& a ) : A(a) { cout << "B copy ctor @ " << this << " from " << &a << endl; }
virtual ~B( void ) { cout << "B dtor @ " << this << endl; }
virtual void f2( void ) { cout << "B::f2" << endl; }
};
class C : public virtual A
{
public:
C( void ) : A() { cout << "C ctor @ " << this << endl; }
C( int i ) : A(i) { cout << "C int ctor @ " << this << endl; }
C( const C& a ) : A(a) { cout << "C copy ctor @ " << this << " from " << &a << endl; }
virtual ~C( void ) { cout << "C dtor @ " << this << endl; }
virtual void f2( void ) { cout << "C::f2" << endl; }
};
template < typename X >
class HoldX : public virtual X
{
public:
template < typename T >
HoldX( T t ) : X( t ) { cout << "T HoldX ctor @ " << this << endl; }
HoldX( void ) : X() { cout << "HoldX ctor @ " << this << endl; }
HoldX( const HoldX& a ) : X(a) { cout << "HoldX copy ctor @ " << this << " from " << &a << endl; }
virtual ~HoldX( void ) { cout << "HoldX dtor @ " << this << endl; }
virtual void f2( void ) { cout << "HoldX::f2" << endl; }
};
template < typename Y, typename X >
class HoldY : public Y, public HoldX< X >
{
public:
template < typename T >
HoldY( T t ) : Y( t ), HoldX< X >( t ) { cout << "T HoldY ctor @ " << this << endl; }
HoldY( void ) : Y(), HoldX< X >() { cout << "HoldY ctor @ " << this << endl; }
HoldY( const HoldY& a ) : Y(a), HoldX< X >(a) { cout << "HoldY copy ctor @ " << this << " from " << &a << endl; }
virtual ~HoldY( void ) { cout << "HoldY dtor @ " << this << endl; }
virtual void f2( void ) { cout << "HoldY::f2" << endl; }
};
template < typename Y, typename X >
class HoldZ : public Y, virtual public HoldX< X >
{
public:
template < typename T >
HoldZ( T t ) : Y(t), HoldX< X >(t) { cout << "\nT HoldZ ctor @ " << this << endl; }
HoldZ( void ) : Y(), HoldX< X >() { cout << "\nHoldZ ctor @ " << this << endl; }
HoldZ( const HoldZ& a ) : Y(a), HoldX< X >(a) { cout << "\nHoldZ copy ctor @ " << this << " from " << &a << endl; }
virtual ~HoldZ( void ) { cout << "HoldZ dtor @ " << this << endl; }
virtual void f2( void ) { cout << "HoldZ::f2" << endl; }
};
int main( void )
{
cout << "Test case for virtual inheritance." << endl;
cout << "\nConstructing HoldX< A > X1;" << endl;
HoldX< A > X1; // OK
cout << "\nConstructing HoldX< A > X2(2);" << endl;
HoldX< A > X2(2); // OK
cout << "\nConstructing HoldX< B > X3;" << endl;
HoldX< B > X3; // OK
cout << "\nConstructing HoldX< B > X4(4);" << endl;
HoldX< B > X4(4); // OK
cout << "\nConstructing HoldX< C > X5;" << endl;
HoldX< C > X5; // OK
cout << "\nConstructing HoldX< C > X6(6);" << endl;
HoldX< C > X6(6); // Huh? Why no A(int) call?
cout << "\nConstructing HoldY< B, A > Y1;" << endl;
HoldY< B, A > Y1; // OK
cout << "\nConstructing HoldY< C, A > Y2;" << endl;
HoldY< C, A > Y2; // OK
cout << "\nConstructing HoldY< C, A >(3) Y3;" << endl;
HoldY< C, A > Y3(3);// Huh? No A(int) again!
cout << "\nConstructing HoldZ< B, A > Z1;" << endl;
HoldZ< B, A > Z1; // OK
cout << "\nConstructing HoldZ< C, A > Z2;" << endl;
HoldZ< C, A > Z2; // OK
cout << "\nConstructing HoldZ< C, A > Z3(3);" << endl;
HoldZ< C, A > Z3(3);// Again no A(int)!
cout << "\nConstructing C C1(1);" << endl;
C C1(1); // OK
cout << "\nTest complete." << endl;
return 0;
}
//
// eof( vinherit.cpp )
//
--------------8162A4C40B6C71CE4742AC88--
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Reico GmbH <Entwicklung@reico.de>
Date: Mon, 11 Sep 2000 23:08:32 GMT Raw View
Hi,
> The reason is because of virtual inheritance, the final class X must
> construct the base class A, and since you leave A out of the initializer
> list, the default constructor is called. I don't see any way to take this
> into account in your design, other than by making the inheritance
> non-virtual.
Can anyone explain this rule? Due to this rule (and only this) virtual
inheritance is quite useless for me in practice. I could imagine the
following rule:
You MAY explicitly state a c'tor for a virtual base class from every
derived class. If you don't, the first virtual base class c'tor reached
during construction is taken.
So you have:
class A {};
class B : virtual A {};
class C : virtual A {};
class D : B, C { }; // A's c'tor is called through B
class D : C, B { }; // A's c'tor is called through C
This would simplify a lot of problems. E.g. transformations of c'tor
arguments done by B (or C) can be used implicitly. And classes derived
from D must not to take care of a proper construction of A (altough they
can).
IMHO this rule could make virtual inheritance much more useful.
The only problems I see:
1. You must be careful while using multple inheritance. But you must it
already today, especially if A has a default c'tor.
2. Some existing code, where A have a default c'tor, could be broken.
Olaf Krzikalla
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: Tue, 12 Sep 2000 15:32:33 GMT Raw View
In article <39BCFBBC.CE91719C@reico.de>, Reico GmbH
<Entwicklung@reico.de> writes
>Can anyone explain this rule? Due to this rule (and only this) virtual
>inheritance is quite useless for me in practice. I could imagine the
>following rule:
>You MAY explicitly state a c'tor for a virtual base class from every
>derived class. If you don't, the first virtual base class c'tor reached
>during construction is taken.
But the rules are not arbitrary. ctors have to be called. If your design
relies on calling a specific non-default ctor for a virtual base it is
extremely fragile because it can, and probably will be, broken when
another class using that virtual base is added to the base classes later
in the process of inheritance.
The moral is that a virtual base class should never depend on non-
default construction. I would go so far as to suggest that a virtual
base class should never have ctors other than the default and copy ones.
Of course the reason that this does not happen is that some people like
to write concrete classes and then use them as virtual bases. That is
also, IMO, a bad idea. Much better is to write your virtual base class
as an ABC without any but the basic two ctors. Derive (non-virtually)
the concrete class, if you want one.
Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Ron Natalie <ron@sensor.com>
Date: Tue, 12 Sep 2000 17:09:30 GMT Raw View
Francis Glassborow wrote:
>
> The moral is that a virtual base class should never depend on non-
> default construction.
Actually the rule is more like, those who inherit from virtual bases shouldn't
depend on the constructor args at all. For it is not they who ultimately specify
them but the most derived class.
Of course, not using anything other than the default is one safe way of
accomplishing this.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Steve Clamage <stephen.clamage@sun.com>
Date: Tue, 12 Sep 2000 17:43:34 GMT Raw View
Reico GmbH wrote:
>
> Hi,
>
> > The reason is because of virtual inheritance, the final class X must
> > construct the base class A, and since you leave A out of the initializer
> > list, the default constructor is called. I don't see any way to take this
> > into account in your design, other than by making the inheritance
> > non-virtual.
>
> Can anyone explain this rule? Due to this rule (and only this) virtual
> inheritance is quite useless for me in practice. I could imagine the
> following rule:
> You MAY explicitly state a c'tor for a virtual base class from every
> derived class. If you don't, the first virtual base class c'tor reached
> during construction is taken.
The C++ object model requires the object's type to be determined by
the constructor that is running, and when a constructor runs,
all of its base classes are fully constructed. Other object models
are possible, but this model ensures that anything that happens
automatically is safe, and that you can't accidently access
unconstructed objects or sub-objects. (Similar considerations
apply to destruction.)
That object model requires that virtual base classes be constructed
first, because any intermediate base class could wind up referring
directly or indirectly to a virtual base class during construction.
Now consider object layout, where no class is empty.
class VB { ... };
class A : public virtual VB { ... };
class B : public virtual VB { ... };
class C : public A, public B { ... };
The location of VB relative to the start of a complete class A or B
object cannot be the same as its location relative to the start
of it as a subobject of a C. (Although relative locations might be
the same for an A or a B, it cannot be the same for both cases.)
Since adjustment of pointers between virtual base and derived
classes (such as when calling virtual functions) depends on the
subobject offsets, the vtable data for a VB in A or B is different
depending on whether the A or B is the complete object or a subobject.
The correct offset information is available only for the most-derived
object, which is why the most-derived constructor must intialize
the virtual base classes.
--
Steve Clamage, stephen.clamage@sun.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Reico GmbH <Entwicklung@reico.de>
Date: Tue, 12 Sep 2000 17:53:52 GMT Raw View
Hi,
Francis Glassborow schrieb:
> But the rules are not arbitrary. ctors have to be called. If your design
> relies on calling a specific non-default ctor for a virtual base it is
> extremely fragile because it can, and probably will be, broken when
> another class using that virtual base is added to the base classes later
> in the process of inheritance.
Do you think of the following:
// take the ABCD example
class X : virtual A {};
// D have to be changed, X is added:
class D : X, B, C {}; // oops, A's ctor calling may be changed
I thougt of things like this, when I wrote: Be careful. But I wouldn't
say: It's extremely fragile. In practice, you can't add base classes as
you want and don't care about all possible side effects. If you add a
base class with a virtual base class, you must know, what you do -
already today.
> The moral is that a virtual base class should never depend on non-
> default construction. I would go so far as to suggest that a virtual
> base class should never have ctors other than the default and copy ones.
> Of course the reason that this does not happen is that some people like
> to write concrete classes and then use them as virtual bases. That is
> also, IMO, a bad idea. Much better is to write your virtual base class
> as an ABC without any but the basic two ctors. Derive (non-virtually)
> the concrete class, if you want one.
I agree, that a virtual base class should be an ABC - conceptional. But
how would you solve the following:
class A {
virtual void f() = 0;
virtual void g() = 0;
// some data members, initialization during construction necessary or
preferred
};
class B : virtual A {
virtual void f() { /*implementation need A's data*/ }
};
class C : virtual A {
virtual void g() { /*implementation need A's data too*/ }
};
class D : B, C {};
I dont think, that I get much advantage by converting A to an ABC. B and
C both must derive from a class with data members, and a class with data
members often needs a c'tor other than the default one. I think, one
motivation for using virtual inheritance is information sharing and this
often requires the use of shared data members.
Olaf Krzikalla
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: Tue, 12 Sep 2000 14:39:46 CST Raw View
In article
<39BE6BA8.89C893B@reico.de>, Reico GmbH <Entwicklung@reico.de> writes
>I agree, that a virtual base class should be an ABC - conceptional. But
>how would you solve the following:
>
>class A {
> virtual void f() = 0;
> virtual void g() = 0;
> // some data members, initialization during construction necessary or
>preferred
They should be initialised, but to default values. Anything else invokes
madness.
>};
>
>class B : virtual A {
> virtual void f() { /*implementation need A's data*/ }
>};
>
>class C : virtual A {
> virtual void g() { /*implementation need A's data too*/ }
>};
>
>class D : B, C {};
>
>
>I dont think, that I get much advantage by converting A to an ABC. B and
>C both must derive from a class with data members, and a class with data
>members often needs a c'tor other than the default one. I think, one
>motivation for using virtual inheritance is information sharing and this
>often requires the use of shared data members.
Unlike Java programmers, I have no problem with an ABC including data,
nor do I have a problem with a user written default ctor (perhaps you
thought a default ctor was always compiler generated? No, a default ctor
is any ctor that can be called without any caller provided data, if a
virtual base class includes data I would strongly advocate that it has a
user written default ctor unless all the data already have default ctors
that initialise them)
>
Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Anders Pytte <anders@milkweed.com>
Date: 10 Sep 2000 11:16:51 -0400 Raw View
in article 39B4ABF7.3B73067@switchco.com, Benjamin Scherrey at
scherrey@switchco.com wrote on 9/8/00 10:53 AM:
> This is a multi-part message in MIME format.
> --------------8162A4C40B6C71CE4742AC88
> Content-Type: text/plain; charset=us-ascii
> Content-Transfer-Encoding: 7bit
>
> I've been trying to implement a dynamic interface/inplementation
> mechanism that makes heavy use of templates and virtual inheritance.
> Basically it allows you to define a class as an interface and to load
> implementations of that interface (i.e. classes that inherit from the
> interface class) at runtime.
>
> Presently, however, I'm having fits getting parameters to the
> implementation constructors to make it up to the interface instance.
> I've attached some sample code that exercises the virtual inheritance
> mechanism and, as you can see from the code, instantiating instances X6,
> Y3, and Z3 refuse to pass the provided parameter up to the virtual
> interface classes constructor.
>
> Unfortunately, I need to be able to have interfaces which don't allow
> default constructors. Plus I'm not too sure about the safety of copying
> some of these values but, for now, I've narrowed my problem down to this
> issue. Is this behavior correct or is my compiler broken (gcc-2.95.2
> under x86 linux)?
>
> thanx very much & later,
>
The reason is because of virtual inheritance, the final class X must
construct the base class A, and since you leave A out of the initializer
list, the default constructor is called. I don't see any way to take this
into account in your design, other than by making the inheritance
non-virtual.
Regards,
Anders.
--
Anders Pytte Milkweed Software
PO Box 32 voice: (802) 586-2545
Craftsbury, VT 05826 email: anders@milkweed.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Pierre Baillargeon <pb@artquest.net>
Date: 10 Sep 2000 12:53:54 -0400 Raw View
You are likely to receive dozens of response to this. The problem is
that the constructor of virtual base class is *always* called from the
most derived class. Of course, if there is no explicit initialization of
the virtual base, its default constructor gets called. For example:
#include <iostream>
struct Base
{
Base() { std::cout << "default" << std::endl; }
Base(int a) { std::cout << "int:" << a << std::endl;}
};
struct Mid : virtual Base
{
Mid() : Base(1) { }
};
struct Bad : Mid
{
Bad() : Mid () { }
};
struct Good : Mid
{
Good() : Base(2), Mid(1) { }
};
int main ()
{
Base base; // Calls Base(), obviously.
Mid mid; // Calls Base(1), expected.
Bad bad; // Calls Base() from Bad, not Base(1) from Mid!!!
Good good; // Calls Base(2) from Good, not Base(1) from Mid.
}
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Carl Daniel" <carl@pixami.com>
Date: 10 Sep 2000 16:00:08 -0400 Raw View
This is not a compiler bug!
The reason A(int) isn't being called is that virtual base classes are always
initialized by the most derived type (see 12.6.2.5). In the case of
HoldX<C>, for example, virtual base A is being initialized by the HoldX<>
ctor, which doesn't call the A(int) ctor, but rather the A() (default) ctor.
-cd
"Benjamin Scherrey" <scherrey@switchco.com> wrote in message
news:39B4ABF7.3B73067@switchco.com...
<snip>
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]