[comp.lang.c++] constructors for virtual base classes

guest@masscomp.UUCP (Mr Guest) (07/05/89)

Consider the following template for a set of classes involving virtual
base classes with constructors.

class common
{
  common () {}
};

class virtual_1 : virtual public common
{
  virtual_1 () : common () {}
};

class virtual_2 : virtual public common
{
  virtual_2 () : common () {}
};

Each of the two classes derived from common has their own constructor
which "call" the constructor for their base class.  Now derive a class
from both of these:

class both : public virtual_1, public virtual_2
{
  both () : virtual_1 (), virtual_2 () {}
};

It seems to me that the constructor for "common" will be called twice.
What am I doing wrong? - Keith

jima@hplsla.HP.COM (Jim Adcock) (07/07/89)

//It seems to me that the constructor for "common" will be called twice.
//What am I doing wrong? - Keith

//Maybe nothing -- I made the following slight mods to your example and
//under my compiler common() only gets called once.  Is this what you
//wanted?  See Lippman pages 360-370.

#include <stdio.h>

class common
{
public:
  common () {printf("common ");}
};

class virtual_1 : virtual public common
{
public:
  virtual_1 () : common () {printf("virtual_1 ");}
};

class virtual_2 : virtual public common
{
public:
  virtual_2 () : common () {printf("virtual_2 ");}
};


class both : public virtual_1, public virtual_2
{
public:
  both () : virtual_1 (), virtual_2 () {printf("both ");}
};

main()
{
  common c; 		printf("\n");
  virtual_1 v1;		printf("\n");
  virtual_2 v2;		printf("\n");
  both b;		printf("\n");
}


/************* gives this output ***************/


common 
common virtual_1 
common virtual_2 
common virtual_1 virtual_2 both 

wmm@sdti.com (0006-William M. Miller(0000)) (07/07/89)

In article <1429@masscomp.UUCP> loepere@westford.ccur.com (Keith Loepere) writes:
>
>Consider the following template for a set of classes involving virtual
>base classes with constructors.
>
>class common
>{
>  common () {}
>};
>
>class virtual_1 : virtual public common
>{
>  virtual_1 () : common () {}
>};
>
>class virtual_2 : virtual public common
>{
>  virtual_2 () : common () {}
>};
>
>class both : public virtual_1, public virtual_2
>{
>  both () : virtual_1 (), virtual_2 () {}
>};
>
>It seems to me that the constructor for "common" will be called twice.
>What am I doing wrong? - Keith

Nothing.  The invocations of the "common" constructor in the two 
intermediate classes are ignored when creating an object of class 
"both." When you make a "both" object, "common()" is invoked, then 
"virtual_1()," then "virtual_2()," then "both()."

This has changed a bit in the most recent 2.0 language definition.  
It used to be the case that a virtual base class could not be 
explicitly initialized.  Now the rules allow for that possibility.  
The new 2.0 definition uses the terminology "most derived class" to 
refer to, for example, your "both" class.  The rules basically say 
that the most derived class is considered to be directly based on 
*every* virtual base class in the inheritance DAG and can therefore 
give arguments to their constructors.  To jazz up your example a 
bit,

class common { public: common(int); };
class virtual_1: virtual public common {
        public: virtual_1(): common(5) {} };
class virtual_2: virtual public common {
        public: virtual_2(): common(10) {} };
class both: virtual public virtual_1, virtual public virtual_2 {
        public: both(): common(15) {} };

virtual_1 v1;
virtual_2 v2;
both b;

The "common" object in "v1" will be initialized with the value 5; in 
"v2," with the value 10; and in "b," with the value 15.
-- 
Non-disclaimer:  My boss and I always see eye-to-eye (every time I look in
the mirror).

...!genrad!mrst!sdti!wmm