13

I have the following code example that doesn't compile:

#include <stdio.h>

namespace my
{
    class base1
    { // line 6
    };

    class base2: private base1
    {
    };

    class derived: private base2
    {
    public:
        // The following function just wants to print a pointer, nothing else!
        void print(base1* pointer) {printf("%p\n", pointer);}
    };
}

The error that gcc prints is:

test.cpp:6: error: `class my::base1' is inaccessible

test.cpp:17: error: within this context

Now, i can guess what the problem is: when looking at the declaration of print, the compiler sees base1 and thinks: base1 is the base-class subobject of derived* this, but you don't have access to it! While i intend that base1 should be just a type name.

How can i see in the C++ Standard that this is a correct behavior, and not a bug in the compiler (i am sure it's not a bug; all compilers i checked behaved so)?

How should i fix this error? All the following fixes work, but which one should i choose?

void print(class base1* pointer) {}

void print(::my:: base1* pointer) {}

class base1; void print(base1* pointer) {}


Edit:

int main()
{
    my::base1 object1;
    my::derived object3;
    object3.print(&object1);
}
curiousguy
  • 8,038
  • 2
  • 40
  • 58
anatolyg
  • 26,506
  • 9
  • 60
  • 134

1 Answers1

12

The section you're looking for is 11.1. It suggests using ::my::base1* to work around this:

[ Note: In a derived class, the lookup of a base class name will find the injected-class-name instead of the name of the base class in the scope in which it was declared. The injected-class-name might be less accessible than the name of the base class in the scope in which it was declared. — end note ]

[ Example:
class A { };
class B : private A { };
class C : public B {
A *p;
// error: injected-class-name A is inaccessible
:: A * q ;
// OK
};
Prasoon Saurav
  • 91,295
  • 49
  • 239
  • 345
Ben Stott
  • 2,218
  • 17
  • 23
  • could you explain what injected-class-name is? – davka Apr 12 '11 at 12:03
  • 1
    Chapter 9, point 2: A class-name is inserted into the scope in which it is declared immediately after the class-name is seen. The class-name is also inserted into the scope of the class itself; this is known as the injected-class-name. For purposes of access checking, the injected-class-name is treated as if it were a public member name. A class-specifier is commonly referred to as a class definition. A class is considered defined after the closing brace of its class-specifier has been seen even though its member functions are in general not yet defined. – Ben Stott Apr 12 '11 at 12:06
  • 1
    If you're happy with the answer provided, @anatolyg, could you please mark this as accepted so that others can see this too? – Ben Stott Apr 12 '11 at 12:29