Search code examples
c++privatecrtp

c++ base private method can be accessed after casting itself to derived class?


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!


Solution

  • 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.