This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: [93J20] C++ private inheritance in several steps
- To: Gunnar Eriksson FOA 72 <guneri at lin dot foa dot se>, gcc at gcc dot gnu dot org, c++support at kai dot com
- Subject: Re: [93J20] C++ private inheritance in several steps
- From: greg at kai dot com (Greg Jaxon)
- Date: Wed, 20 Oct 1999 10:59:30 CDT
- Cc: Alexandre Oliva <oliva at dcc dot unicamp dot br>
- Organization: Kuck and Associates, Champaign IL
Mr. Eriksson,
It seems that the simple class hierarchy in your example is
falling prey to a strict interpretation of a late change made just
before the C++ standard was approved. The feature is known as
class name injection, and we describe it and its annoying
consequences at
http://www.kai.com/C_plus_plus/v3.4/doc/UserGuide/chapter_9.html#class-name-injection
This together with the member access rules of section 11
(one of which notes that:
11.2.3: [Note: A member of a private base class might be inaccessible as an inherited member name, but
accessible directly. Because of the rules on pointer conversions (conv.ptr) and explicit casts
(expr.cast), a conversion from a pointer to a derived class to a pointer to an inaccessible base class
might be ill-formed if an implicit conversion is used, but well-formed if an explicit cast is used.
...]
... and with the rules of derived class name lookup
have combined to produce this code's inability for class C to
refer to the public class A directly. When I compile using
--no_class_name_injection your original code works
as it always did. I tried to follow the standards advice of using
fully qualified names more often, and I just got into more
trouble. What turned out to work was Arch Robison's suggestion
from our website, that you insert a typedef to explicit export
from B the typename of A.
Frankly it looks a little ridiculous, but in the world of access
control, it probably makes sense. Fortunately it is not my job to
defend the ISO committee's design.
Greg Jaxon
KAI Optimizing Compilers
class A {
public: A(int d=17) : data(d) {}; int data;
};
class B : private A {
public:
typedef A A; // <<<<< inserted
const A& getA() const {return *this;}
};
class C : private B {
public: const A& getA() const {return B::getA();}
};
#include <iostream>
using namespace std;
int main()
{
C c0;
cout << "c0.getA().data: " << c0.getA().data << endl;
return 0;
}