5

I recently had to do something like this:

class A { };
class B : private A { };
class C : public B {
    public:
        A *myA;
};

int main() {
    return 0;
}

And I get an error in the three compilers I tried. When I changed the declaration of myA to ::A *myA everything works ok. I poked around in the C++ standard and found Section 11.2, paragraph 3 where it says:

Note: A member of a private base class might be inaccessible as an inherited member name, but accessible directly.

Which is relevant, but unclear. Why is the name A inaccessible? What problems would occur if A was not hidden?

Thanks,
-Ben

David G
  • 94,763
  • 41
  • 167
  • 253
Ben
  • 193
  • 5
  • I would expect that to compile since the class C is just defining a variable myA which is a pointer to a variable of type class A. Was myA defined in either class B or class A as a member of one of those classes? – Richard Chambers May 30 '13 at 01:15
  • Nope. If you copy and paste that code into your editor, you should get the same error. At least with clang, gcc, and Visual Studio 2010. – Ben May 30 '13 at 01:16
  • 2
    possible duplicate of [Why a simple mention of base pointer/reference in subsequent privately derived classes is forbidden?](http://stackoverflow.com/questions/13927116/why-a-simple-mention-of-base-pointer-reference-in-subsequent-privately-derived-c) – perreal May 30 '13 at 01:22
  • 1
    The name `A` is injected into the class `A` and inherited into `B`. [class]/2 tells us "For purposes of access checking, the injected-class-name is treated as if it were a public member name." And that is why the injected-class-name `A` cannot be accessed from `C`. – dyp May 30 '13 at 01:26
  • 1
    also see: http://stackoverflow.com/a/15342557/390913 – perreal May 30 '13 at 01:28
  • Thanks, perreal. I did a search, but I guess I missed that. I'll read those links. – Ben May 30 '13 at 01:30

1 Answers1

3

Where it could "go wrong":

namespace nmsp
{
    class A {};
}

class A {};

class B : private nmsp::A
{
    // well-formed:
    A* d; // refers to the injected-class-name nmsp::A!!
};

class C : public B
{
    // ill-formed
    A* p; // refers to the injected-class-name nmsp::A!!
};

It should not depend on the access-specifier in the base-clause whether ::A or nmsp::A is used, otherwise it'd be error-prone IMO.

dyp
  • 38,334
  • 13
  • 112
  • 177