Topic: Dominance, access + virtuals


Author: Douglas Gilbert <Douglasg@sydpo4.aus.unisys.com>
Date: 1996/10/22
Raw View
Since reading about the following technique in Barton + Nackman, I have
been frustrated by various versions of MSVC (1.5, 4.0 + 4.2) that refuse
to accept it. It involves dominance, virtual functions and base classes,
and access control.

class DogInterface {
public:
 virtual void bark() = 0;
};

class DogImplementation : public virtual DogInterface {
public:
 void bark() { /* ... */ }
};

class Poodle : public virtual DogInterface, private DogImplementation
{ };

int main()
{
 Poodle dog;
 DogInterface * dip = &dog;

 dip->bark(); // ok
 dog.bark(); // MSVC: error C2248: 'bark' : cannot access
   // public member declared in class
   // 'DogImplementation'
 return 0;
}

>From memory this works with Borland and gcc. Section 11.7 [class.paths]
of the CD gives a similar example but without the virtual function.
Section 10.3 [class.virtual] notes that "a virtual member function does
not need to be visible to be overridden ...". Section 10.3 has several
examples around this area. The term "dominance" introduced in the ARM
seems to have slipped out of the CD as well. Is this legal code?

Doug Gilbert
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: bradds@concentric.net (Bradd W. Szonye)
Date: 1996/10/23
Raw View
Douglas Gilbert <Douglasg@sydpo4.aus.unisys.com> wrote in article
<326C15C6.3677@sydpo4.aus.unisys.com>...
>
> class DogInterface {
> public:
>  virtual void bark() = 0;
> };
>
> class DogImplementation : public virtual DogInterface {
> public:
>  void bark() { /* ... */ }
> };
>
> class Poodle : public virtual DogInterface, private DogImplementation
> { };
>
> int main()
> {
>  Poodle dog;
>  DogInterface * dip = &dog;
>
>  dip->bark(); // ok
>  dog.bark(); // MSVC: error C2248: 'bark' : cannot access
>    // public member declared in class
>    // 'DogImplementation'
>  return 0;
> }

The rules about 'dominant' virtual functions appears in the working papers
under [class.virtual] as the term 'final overrider' of a virtual function.
Since DogImplementation::bark() overrides DogInterface::bark(), it is the
'final overrider' in your lattice; calls to dog.bark() resolve to
DogImplementation::bark().

By [class.member.lookup], DogImplementation::bark() also hides the name
'bark' from DogInterface, because the derivation is virtual. Therefore,
'bark' is an unambiguous name in Poodle, and it is private because it
inherits from a private derivation.

These are two related but subtly different rules: the first rule says which
version of a virtual function to call; the second rule says whether the
name is unambiguous. If the function or base is non-virtual, then the name
is ambiguous. In this case, however, the resolution of dog.bark() leads to
an unambiguous yet inaccessible member of Poodle.

In other words: you should not derive from the same class both publicly and
privately. In relationship terms, you're saying both 'Poodle is-a
DogInterface' and 'Poodle is-not-really-a DogInterface' at the same time.
You open up a 'type hole' by allowing both an accessible and an
inaccessible path to virtual functions at the same time--thus dip-bark() is
accessible but dog.bark() is not.

You should solve the problem either by making members of DogImplementation
visible in Poodle through using-declarations or by overriding 'hidden'
members in Poodle and calling the DogImplementation functions as part of
their definition.

By the way, the comment about a virtual function not needing to be visible
to be overridden applies to cases like this:

struct foo { virtual void F(T1); };
struct goo : public foo { void F(T2); }; // F(T1) not visible here
struct bar : public goo { void F(T1); }; // overrides foo::F(T1), which is
not visible

--
Bradd W. Szonye
bradds@concentric.net
http://www.concentric.net/~bradds
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: Marc Girod <girod@trshp.trs.ntc.nokia.com>
Date: 1996/10/24
Raw View
>>>>> "DG" == Douglas Gilbert <Douglasg@sydpo4.aus.unisys.com> writes:

DG> Since reading about the following technique in Barton + Nackman, I have
DG> been frustrated by various versions of MSVC (1.5, 4.0 + 4.2) that refuse
DG> to accept it. It involves dominance, virtual functions and base classes,
DG> and access control.

>> From memory this works with Borland and gcc. Section 11.7 [class.paths]
DG> of the CD gives a similar example but without the virtual function.
DG> Section 10.3 [class.virtual] notes that "a virtual member function does
DG> not need to be visible to be overridden ...". Section 10.3 has several
DG> examples around this area. The term "dominance" introduced in the ARM
DG> seems to have slipped out of the CD as well. Is this legal code?

It doesn't work with HP compiler either, and they managed to convince
me that it is right so...

 Accessibility is applied after name lookup.

Anyway, once you have defined an interface, you should use it... So,
it is not a great problem (?)

Regards!

--
Marc Girod                                   Phone:  +358-9-511 27703
Nokia Telecommunications   P.O. Box 370      Fax:    +358-9-511 27432
Kilo RD 4                  00045 NOKIA Group marc.girod@ntc.nokia.com
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]