struct B {};
struct D : private B {
B* fun () { return new D; } // ok
}
struct DD : public D {
B* foo () { return 0; } // error: ‘struct B B::B’ is inaccessible !
};
This error seems unreasonable to me. If we can use simple B*
in global scope then why not in its privately derived classes? g++ demo.
We are Not trying to convert DD*
to B*
, which is forbidden by the language rules (this, this, this are related questions).
Note that, if I change B* foo()
to int foo()
, things go fine.
similarly a derived object is a base class object (as it's a sub class), so it can be pointed to by a base class pointer. However, a base class object is not a derived class object so it can't be assigned to a derived class pointer.
Explanation: A base class pointer can point to a derived class object, but we can only access base class member or virtual functions using the base class pointer because object slicing happens when a derived class object is assigned to a base class object.
A pointer reference is polymorphic, since it can reference objects of different dynamic type.
So apparently the compiler thinks B
is referring to the private constructor of B
rather than the type.
Qualifying B
apparently fixes that error:
class B* foo () { return 0; }
or this:
::B* foo () { return 0; }
I don't know why that's happening, but maybe this will help.
Update: maybe it's related to 11.2.4 of standard? The only problem is that my standardese isn't good enough to fully understand it.
(sorry for the image, copy/pasting isn't working for me)
A quick look-up for injected-class-name in the Standard yields:
§11.1 [class.access.spec]
5/ [ 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 };
—end example ]
I believe this is eerily close to your example ;)
Note clang 3.0's stack, which is slightly more explicit:
$ clang++ -fsyntax-only test.cpp
test.cpp:6:5: error: 'B' is a private member of 'B'
B* foo () { return 0; } // error: ‘struct B B::B’ is inaccessible !
^
test.cpp:2:12: note: constrained by private inheritance here
struct D : private B {
^~~~~~~~~
test.cpp:1:8: note: member is declared here
struct B {};
^
1 error generated.
Here we see that B
is accessed through D
, instead of directly picked up in the global namespace.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With