i found this when I used CRTP (curiously recurring template pattern).
template <typename T>
class Base {
private:
void f() {
//when T has its own f(), it calls that
//when T doesn't have, it calls itself, which is invoked recursively
//but i expect the compiler to complain that f() is private when T doesn't have its own f()
static_cast<T*>(this)->f();
}
public:
void g() {
f();
}
};
class Derived : public Base<Derived> {};
I thought i understand public
, protected
and private
, but for this case, it looks like i am wrong. Any explanation is appreciated!
This will only work if the shadowing declaration is public
. See this example:
class Derived : public Base<Derived> {
private:
void f() { }
};
void x(Derived* d) {
d->g();
}
You get:
<source>: In instantiation of 'void Base<T>::f() [with T = Derived]':
<source>:13:9: required from 'void Base<T>::g() [with T = Derived]'
<source>:23:10: required from here
<source>:8:9: error: 'void Derived::f()' is private within this context
static_cast<T*>(this)->f();
^~~~~~~~~~~
<source>:19:10: note: declared private here
void f() { }
^
If the function is not shadowed in Derived
, the call is the same as this->Base<Derived>::f()
, which has to be legal, as Base
is the only class that can access it.
It's also possible that your confusion came from accessing a seemingly different object. Keep in mind that access modifiers restrict access by scope, not by instance. Any method declared in Base
can touch any Base
instance's private members, not just this
's.