Topic: Virtual base classes and access control


Author: Steve Clamage <stephen.clamage@Eng.Sun.COM>
Date: 1997/07/25
Raw View
Gary Mussar wrote:
>
> We have the following class heirarchy and found that 3 of the
> recent compilers we tried accept it and 3 reject it with an
> error.
>
> class foo
> {
>    foo();
>    ~foo();
> };
>
> class bar : virtual private foo { };
>
> class FooBar : public bar
> {
>    FooBar();
>    ~FooBar();
> };
>
> The problem is an interpretation of the ANSI C++ draft which states
> that the constructors/destructors for virtual base classes must be
> called from the constructor/destructor of the most derived class.
>
> It appears that some compiler vendors have interpretted this to
> mean that at the object level, the most derived class must have
> access to these constructors/destructors and generate an error
> for the above example.

Yes, of course. The constructor of the most-derived class invokes
the constructor of the virtual base class. The foo constructor must
be accessible to the FooBar constructor. But the code as shown
does not require such access. More below.

> Other vendors appear to interpret this to be implementation detail
> that has been specified to ensure that all compliant compilers
> invoke the virtual base class constructors in the same order, etc..

Accessibility is not an implementation detail, it is part of the
language definition. A private constructor is not accessible to
any of its derived classes (unless they are friends), and thus
cannot be invoked by them.

A separate question is when the accessibility is needed. For
example, a class with a private destructor and no friends cannot
be destroyed. But if you never use the class in a context
where it needs destruction, you have no error.

> Should the addition of the key word virtual to a base class affect
> the access (public, protoected, private) or requirement for access
> to class members?

No.

> IMO, I feel such an access change leads to a language inconsistency.
> (Removing the key word virtual in the above example will allow
> the above example to compile on all 6 compilers.)

Even with the virtual keyword, the code shown above could compile,
because none of the code needs access to foo::foo(). If you add a
definition of FooBar::FooBar() you should get errors from all
compilers, with or without the virtual keyword.

It isn't until a bar or FooBar constructor is compiled, or until an
object of type foo, or a type derived from foo, is created that
access to the foo constructor is needed. Since the code above does
none of those things, no error message is needed.

If you replace "FooBar();" with "FooBar(){}" and still don't get
an error, you should complain to the vendor.

--
Steve Clamage, stephen.clamage@eng.sun.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
]





Author: Steve Clamage <stephen.clamage@Eng.Sun.COM>
Date: 1997/07/26
Raw View
Gary Mussar wrote:
>
> We have the following class heirarchy and found that 3 of the
> recent compilers we tried accept it and 3 reject it with an
> error.
>
> class foo
> {
>    foo();
>    ~foo();
> };
>
> class bar : virtual private foo { };
>
> class FooBar : public bar
> {
>    FooBar();
>    ~FooBar();
> };
>
> The problem is an interpretation of the ANSI C++ draft which states
> that the constructors/destructors for virtual base classes must be
> called from the constructor/destructor of the most derived class.
>
> It appears that some compiler vendors have interpretted this to
> mean that at the object level, the most derived class must have
> access to these constructors/destructors and generate an error
> for the above example.

Yes, of course. The constructor of the most-derived class invokes
the constructor of the virtual base class. The foo constructor must
be accessible to the FooBar constructor. But the code as shown
does not require such access. More below.

> Other vendors appear to interpret this to be implementation detail
> that has been specified to ensure that all compliant compilers
> invoke the virtual base class constructors in the same order, etc..

Accessibility is not an implementation detail, it is part of the
language definition. A private constructor is not accessible to
any of its derived classes (unless they are friends), and thus
cannot be invoked by them.

> Should the addition of the key word virtual to a base class affect
> the access (public, protoected, private) or requirement for access
> to class members?

No.

> IMO, I feel such an access change leads to a language inconsistency.
> (Removing the key word virtual in the above example will allow
> the above example to compile on all 6 compilers.)

Even with the virtual keyword, the code shown above could compile,
because none of the code needs access to foo::foo(). If you add a
definition of FooBar::FooBar() you should get errors from all
compilers, with or without the virtual keyword.

It isn't until a bar or FooBar constructor is compiled, or until an
object of type foo, or a type derived from foo, is created that
access to the foo constructor is needed. Since the code above does
none of those things, no error message is needed.

If you replace "FooBar();" with "FooBar(){}" and still don't get
an error, you should complain to the vendor.

--
Steve Clamage, stephen.clamage@eng.sun.com

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]





Author: "Gary Mussar" <mussar@nortel.ca>
Date: 1997/07/28
Raw View
Steve Clamage wrote:
> > Other vendors appear to interpret this to be implementation detail
> > that has been specified to ensure that all compliant compilers
> > invoke the virtual base class constructors in the same order, etc..
>
> Accessibility is not an implementation detail, it is part of the
> language definition. A private constructor is not accessible to
> any of its derived classes (unless they are friends), and thus
> cannot be invoked by them.
>
> > Should the addition of the key word virtual to a base class affect
> > the access (public, protoected, private) or requirement for access
> > to class members?
>
> No.

But it does affect the REQUIREMENT for access. When FooBar inherits
from Bar which privately inherits from Foo there is no requirement
for FooBar to have access to Foo's ctor. When Bar adds the keyword
virtual to its private inheritance from Foo, then FooBar does
require access to Foo's ctor.

The developers were looking at this from the same perspective as adding
"inline" to a function declaration. The addition of "inline" shouldn't
affect the user's view of the interface or behaviour of the function.
Similarily, adding the keyword virtual to a function shouldn't affect
the interface or access requirements when invoking that function
(although the behaviour of the function might change).

The counter argument is that adding "virtual" to a base class really
does change its behaviour (now being a shared implementation and more
importantly requires some kind of shared/consistent initialization of
the VB) and thus the user shouldn't be too surprised that it has an
effect on the VB's interface (or interface requirements).

> Even with the virtual keyword, the code shown above could compile,
> because none of the code needs access to foo::foo(). If you add a
> definition of FooBar::FooBar() you should get errors from all
> compilers, with or without the virtual keyword.

Sorry I didn't add an implementation of FooBar::FooBar() to the text.
I was just illustrating the hierarchy. I also errored by not making
Foo's ctor/dtor accessible to Bar. Mea culpa.

--
Gary Mussar <mussar@nortel.ca>   Phone: (613) 763-4937
Nortel                           FAX:   (613) 763-9406
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: "Gary Mussar" <mussar@nortel.ca>
Date: 1997/07/16
Raw View

We have the following class heirarchy and found that 3 of the
recent compilers we tried accept it and 3 reject it with an
error.

class foo
{
   foo();
   ~foo();
   ...
};

class bar : virtual private foo
{
   ...
};

class FooBar : public bar
{
   FooBar();
   ~FooBar();
   ...
};


The problem is an interpretation of the ANSI C++ draft which states
that the constructors/destructors for virtual base classes must be
called from the constructor/destructor of the most derived class.

It appears that some compiler vendors have interpretted this to
mean that at the object level, the most derived class must have
access to these constructors/destructors and generate an error
for the above example.

Other vendors appear to interpret this to be implementation detail
that has been specified to ensure that all compliant compilers
invoke the virtual base class constructors in the same order, etc..

Should the addition of the key word virtual to a base class affect
the access (public, protoected, private) or requirement for access
to class members?

IMO, I feel such an access change leads to a language inconsistency.
(Removing the key word virtual in the above example will allow
the above example to compile on all 6 compilers.)

--
Gary Mussar <mussar@nortel.ca>   Phone: (613) 763-4937
Nortel                           FAX:   (613) 763-9406
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: "Gary Mussar" <mussar@nortel.ca>
Date: 1997/07/23
Raw View
I have posted this query in comp.lang.c++.moderated and in this
newsgroup and no-one seems to have any opinion on the problem.
Does this mean that the problem description is unclear or that the
problem is not worth commenting on? I had hoped that some C++
language gurus could discuss the interpretation of the standard
here before the next ANSI meeting.

Gary Mussar wrote:

We have the following class heirarchy and found that 3 of the
recent compilers we tried accept it and 3 reject it with an
error.

class foo
{
   foo();
   ~foo();
   ...
};

class bar : virtual private foo
{
   ...
};

class FooBar : public bar
{
   FooBar();
   ~FooBar();
   ...
};

The problem is an interpretation of the ANSI C++ draft which states
that the constructors/destructors for virtual base classes must be
called from the constructor/destructor of the most derived class.

It appears that some compiler vendors have interpretted this to
mean that at the object level, the most derived class must have
access to these constructors/destructors and generate an error
for the above example.

Other vendors appear to interpret this to be implementation detail
that has been specified to ensure that all compliant compilers
invoke the virtual base class constructors in the same order, etc..

Should the addition of the key word virtual to a base class affect
the access (public, protoected, private) or requirement for access
to class members?

IMO, I feel such an access change leads to a language inconsistency.
(Removing the key word virtual in the above example will allow
the above example to compile on all 6 compilers.)

--
Gary Mussar <mussar@nortel.ca>   Phone: (613) 763-4937
Nortel                           FAX:   (613) 763-9406
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]