Topic: strange constructor behaviour


Author: Ralf Walther <rw@neurotec.de>
Date: 1998/10/02
Raw View
Hi!

I have to apologize for my so stupid question. After checks with further
compilers,
I've realized the reason for this now obviously non-strange behaviour on my
own.
Now I've improved my experiences with virtual inheritance.

Thanks for all answers

Ralf
---
[ 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@robinton.demon.co.uk>
Date: 1998/10/02
Raw View
In article <36126AD8.6C77121A@neurotec.de>, Ralf Walther
<rw@neurotec.de> writes
>If you instantiate an object of type VA_i, everything works fine, the
>ctor initializes the ctor of A_i with an int (say 1).
>BUT, if you instantiate an object of type VA, ...
>
>THE EXPLICIT CALL OF THE CTOR IS IGNORED, AS IF IT'S COMMENTED

and that is entirely correct.  Virtual bases are nasty.  The rule (if I
remember it correctly) is

virtual base classes are intialised left to right, depth first.  This
can create some really nasty counter-intuitive situations wrt to object
layout.

class A {};
class B {};

class VA: virtual public A {};
class VB: virtual public B {};

class AB: public VA, public VB {};

// class A will be constructed first then class B, followed by VA and VB

class BAB : virtual public B, class AB {}

// now class B is constructed first (left to right, B is now leftmost)

This means that the layout of the AB subobject might be different from
the layout of an AB complete object.


>
>I've checked this fact with g++ 2.8.1 and HP c++ compiler on HP-UX 10.20
>
>Does anyone know a hint on this behaviour ??? I think it's strange, but
>certainly I hope someone can explain this fact, so I can solve my

It is always the task of the most derived class to directly call the
ctors for all virtual bases.  Which is an excellent reason for avoiding
non-trivial ctors in virtual base classes.


>problem.
>
>Thanks in advance

Francis Glassborow      Chair of 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: "Nate Lewis" <nlewis@mindspring.com>
Date: 1998/10/02
Raw View
Ralf Walther wrote in message <36126AD8.6C77121A@neurotec.de>...
>If you instantiate an object of type VA_i, everything works fine, the
>ctor initializes the ctor of A_i with an int (say 1).
>BUT, if you instantiate an object of type VA, ...
>
>THE EXPLICIT CALL OF THE CTOR IS IGNORED, AS IF IT'S COMMENTED
>
>I've checked this fact with g++ 2.8.1 and HP c++ compiler on HP-UX
10.20
>
>Does anyone know a hint on this behaviour ??? I think it's strange, but
>certainly I hope someone can explain this fact, so I can solve my
>problem.

This is correct behavior when you're using virtual inheritance.  A
virtual base class might be shared among one or several classes;
however, a constructor for an object should only be called once.  To
accomplish this, the call to a virtual base class constructor is made
from the constructor of the complete object, the most derived type; if
you don't make it explicit it is done implicitly.  If you remove the
default value from A_i's constructor you'll see a compile error from
VA's constructor.

If this comes as a surprise to you, is virtual inheritance perhaps not
the mechanism you intend to use?

--
Nate Lewis, MCSD
nlewis@mindspring.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: Ralf Walther <rw@neurotec.de>
Date: 1998/10/01
Raw View
Hi!

It's nothing strange in initializing a base class via
explicit call to a parameterized constructor (ctor).
BUT look at this

class sk_A <--------- class A_i
             virtual     ^
                         |
                         | virtual
                         |

class sk_VA <--------- class VA_i <--------- class VA
             virtual                 virtual

[code of test program and traces are below, ctor of VA_i calls the ctor
of
A_i with an argument]


If you instantiate an object of type VA_i, everything works fine, the
ctor initializes the ctor of A_i with an int (say 1).
BUT, if you instantiate an object of type VA, ...

THE EXPLICIT CALL OF THE CTOR IS IGNORED, AS IF IT'S COMMENTED

I've checked this fact with g++ 2.8.1 and HP c++ compiler on HP-UX 10.20

Does anyone know a hint on this behaviour ??? I think it's strange, but
certainly I hope someone can explain this fact, so I can solve my
problem.

Thanks in advance

 Ralf (rw@neurotec.de)


traces of test program

-----------------
creation of type VA_i, everything is ok
-----------------
ctor sk_VA
ctor sk_A
ctor A_i mode: 1   <===== that's ok, it's the right value passed of VA_i
ctor
ctor VA_i
dtor ~VA_i
dtor ~A_i
dtor ~sk_A
dtor ~sk_VA
*********************
ctor sk_A
ctor A_i mode: 0   <===== that's NOT ok, the ctor call
ctor sk_VA                with argument (1) has been ignored
ctor VA_i
ctor VA
dtor ~VA
dtor ~VA_i
dtor ~sk_VA
dtor ~A_i
dtor ~sk_A



class sources and test program
------------------------------
#include <iostream.h>
class sk_A
{
public:
   sk_A()
   {
      cout << "ctor sk_A " << endl; cout.flush ();
   };

   ~sk_A()
   {
      cout << "dtor ~sk_A " << endl; cout.flush ();
   }
};

class A_i : virtual public sk_A
{
public:
   A_i(const int mode = 0)
   {
      cout << "ctor A_i mode: " << mode << " " << endl; cout.flush ();
   };

   ~A_i()
   {
      cout << "dtor ~A_i " << endl; cout.flush ();
   }
};

class sk_VA
{
public:
   sk_VA()
   {
      cout << "ctor sk_VA " << endl; cout.flush ();
   };

   ~sk_VA()
   {
      cout << "dtor ~sk_VA " << endl; cout.flush ();
   }
};

class VA_i : virtual public A_i, virtual public sk_VA
{
public:
   VA_i() : A_i (1)
   {
      cout << "ctor VA_i " << endl; cout.flush ();
   };

   ~VA_i()
   {
      cout << "dtor ~VA_i "  << endl; cout.flush ();
   }
};

class VA : virtual public VA_i
{
public:
   VA()
   {
      cout << "ctor VA " << endl; cout.flush ();
   };

   ~VA()
   {
      cout << "dtor ~VA "  << endl; cout.flush ();
   }
};

void main ()
{
       VA_i* aVA_i = new VA_i;
       delete aVA_i;

       cout << "*********************" << endl; cout.flush ();

       VA* aVA = new VA;
       delete aVA;

}
---
[ 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: jim.hyslop@leitch.com
Date: 1998/10/01
Raw View
In article <36126AD8.6C77121A@neurotec.de>,
  Ralf Walther <rw@neurotec.de> wrote:
> Hi!
>
> It's nothing strange in initializing a base class via
> explicit call to a parameterized constructor (ctor).
> BUT look at this
>
> class sk_A <--------- class A_i
>              virtual     ^
>                          |
>                          | virtual
>                          |
>
> class sk_VA <--------- class VA_i <--------- class VA
>              virtual                 virtual
>
> [code of test program and traces are below, ctor of VA_i calls the ctor
> of
> A_i with an argument]
>
> If you instantiate an object of type VA_i, everything works fine, the
> ctor initializes the ctor of A_i with an int (say 1).
> BUT, if you instantiate an object of type VA, ...
>
> THE EXPLICIT CALL OF THE CTOR IS IGNORED, AS IF IT'S COMMENTED
[snip]

> class VA : virtual public VA_i
> {
> public:
>    VA()
>    {
>       cout << "ctor VA " << endl; cout.flush ();
>    };
[snip]

With virtual inheritance, it is up to the most-derived class to intialize
base classes, thus VA_i's call to initalize A will (properly) be ignored.
This is to prevent multiple initialization of virtual base classes.

Section 12.6.2 of the Standard states "All sub-objects representing virtual
base classes are initialized by the constructor of the most derived class
(1.8). If the constructor of the most derived class does not specify a
mem-initializer for a virtual base class V, then V's default constructor is
called to initialize the virtual base class subobject."  So your program is
behaving correctly.

Jim

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own


[ 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: AllanW@my-dejanews.com
Date: 1998/10/01
Raw View
In article <36126AD8.6C77121A@neurotec.de>,
  Ralf Walther <rw@neurotec.de> wrote:

> It's nothing strange in initializing a base class via
> explicit call to a parameterized constructor (ctor).
> BUT look at this
>
> class sk_A <--------- class A_i
>              virtual     ^
>                          |
>                          | virtual
>                          |
>
> class sk_VA <--------- class VA_i <--------- class VA
>              virtual                 virtual
>
> [code of test program and traces are below, ctor of VA_i calls the ctor
> of
> A_i with an argument]
>
> If you instantiate an object of type VA_i, everything works fine, the
> ctor initializes the ctor of A_i with an int (say 1).
> BUT, if you instantiate an object of type VA, ...
>
> THE EXPLICIT CALL OF THE CTOR IS IGNORED, AS IF IT'S COMMENTED

THIS IS BY DESIGN. THE CTOR OF CLASS A_i IS *cough* *hack-hack*
*cough* uh... sorry. Something in my throat...

This is by design. The constructor of clas A_i is called from
only one place; that place is the most-derived object, in this
case VA.

You could modify VA's constructor to supply an
initialization-parameter-list for A_i.

--
AllanW@my-dejanews.com is a "Spam Magnet" -- never read.
Please reply in USENET only, sorry.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own


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