[comp.lang.c++] virtual base class & function member ambiguity question

brucec@phoebus.phoebus.labs.tek.com (Bruce Cohen;;50-662;LP=A;) (08/28/90)

Is this a bug in cfront 2.0, or am I not understanding how virtual base
classes work?

Question 1:
I have a simple test case with an inheritance DAG that goes like:

                        Root
                         |
                       Derived
                    _____|_____
                    |         |
                DerivedVR1  DerivedVR2
                    |_________|
                         |
                        Leaf

Leaf is derived virtually from both its base classes. I get the error:

test.C", line 47: error: ambiguous Root::Print() and Root::Print() (one not in virtual base)
1 error

I thought that because Leaf is derived virtually from its base classes any
reference to Print() must unambiguously refer to Root::Print(), of which
there is only one.  Is this not so?

Here's the file:
// test virtual base function inheritance
#include <stdio.h>

class Root
{
  public:
    Root(char* s = "Root") { string = s; }
    void Print() {printf("%s\n", string); }

  protected:
    char* string;
};

class Derived : public Root
{
  public:
    Derived(char* s = "Derived");
};
Derived::Derived(char* s) : Root (s) { }

class DerivedVR1 : public Derived
{
  public:
    DerivedVR1(char* s = "DerivedVR1");
};
DerivedVR1::DerivedVR1(char* s) : Derived (s) { }

class DerivedVR2 : public Derived
{
  public:
    DerivedVR2(char* s = "DerivedVR2");
};
DerivedVR2::DerivedVR2(char* s) : Derived (s) { }

class Leaf : public virtual DerivedVR2, public virtual DerivedVR1
{
  public:
    Leaf(char* s = "Leaf");
    void PrintLeaf();
};

Leaf::Leaf(char* s) : DerivedVR1 (s),  DerivedVR2 (s) { }

void Leaf::PrintLeaf()
{
    printf("Leaf\t\t\t");
    Print();
}

main()
{
    Root root;
    Derived derived;
    DerivedVR1 derivedVR1;
    DerivedVR2 derivedVR2;
    Leaf leaf;

    printf("Class\t\t\tPrintString\n");
    printf("Root\t\t\t"); root.Print();
    printf("Derived\t\t\t"); derived.Print();
    printf("DerivedVR1\t\t"); derivedVR1.Print();
    printf("DerivedVR2\t\t"); derivedVR2.Print();
    leaf.PrintLeaf();
}


Question 2:
In the same program, I now derive Leaf from DerivedVR1 and Derived, and I get
the error:

"test.C", line 36: error: virtual  Derived inaccessible because of  Derived in  DerivedVR1

Why?

---------------------------------------------------------------------------
NOTE: USE THIS ADDRESS TO REPLY, REPLY-TO IN HEADER MAY BE BROKEN!
Bruce Cohen, Computer Research Lab        email: brucec@tekcrl.labs.tek.com
Tektronix Laboratories, Tektronix, Inc.                phone: (503)627-5241
M/S 50-662, P.O. Box 500, Beaverton, OR  97077

--
---------------------------------------------------------------------------
NOTE: USE THIS ADDRESS TO REPLY, REPLY-TO IN HEADER MAY BE BROKEN!
Bruce Cohen, Computer Research Lab        email: brucec@tekcrl.labs.tek.com
Tektronix Laboratories, Tektronix, Inc.                phone: (503)627-5241
M/S 50-662, P.O. Box 500, Beaverton, OR  97077

garnett@coupe.bellcore.com (Michael Garnett) (08/28/90)

In article <BRUCEC.90Aug27121305@phoebus.phoebus.labs.tek.com>,
brucec@phoebus.phoebus.labs.tek.com (Bruce Cohen;;50-662;LP=A;) writes:
|> Is this a bug in cfront 2.0, or am I not understanding how virtual
base
|> classes work?
|> 
|> Question 1:
|> I have a simple test case with an inheritance DAG that goes like:
|> 
|>                         Root
|>                          |
|>                        Derived
|>                     _____|_____
|>                     |         |
|>                 DerivedVR1  DerivedVR2
|>                     |_________|
|>                          |
|>                         Leaf
|> 
...
|> Here's the file:
|> // test virtual base function inheritance
...
|> 
|> class DerivedVR1 : public Derived
|> {
|>   public:
|>     DerivedVR1(char* s = "DerivedVR1");
|> };
|> DerivedVR1::DerivedVR1(char* s) : Derived (s) { }
|> 
|> class DerivedVR2 : public Derived
|> {
|>   public:
|>     DerivedVR2(char* s = "DerivedVR2");
|> };
|> DerivedVR2::DerivedVR2(char* s) : Derived (s) { }
|> 
|> class Leaf : public virtual DerivedVR2, public virtual DerivedVR1
|> {
|>   public:
|>     Leaf(char* s = "Leaf");
|>     void PrintLeaf();
|> 

I'm answering this in a hurry but...

shouldn't the class DerivedVR1 be 
         class DerivedVR1 : public virtual Derived 
           ...
and the DerivedVR1 class likewise be
         class DerivedVR2 : public virtual Derived
           ...

and the class Leaf be simply
         class Leaf : public DerivedVR1, public DerivedVR2

reason: (possible reason? <smile>)
   It's the 'Derived' class that you want to avoid multiple copies of..
   ...not the DerivedVR2 and DerivedVR1 classes...
   Each of them (DerivedVR[12]) must have a copy of Derived ...
   ...but Leaf needs only one copy....
   ...yet still needs BOTH DerivedVR1 and DerivedVR2



               Michael