Consider the following snippet of code:
#include <iostream>
class Base {
public:
Base() {
std::cout << "Base::constr" << std::endl;
print();
}
virtual ~Base() = default;
void print() const { printImpl(); }
private:
virtual void printImpl() const {
std::cout << "Base::printImpl" << std::endl;
}
};
class Derived : public Base {
public:
Derived() {
std::cout << "Derived::constr" << std::endl;
}
private:
void printImpl() const override {
std::cout << "Derived::printImpl" << std::endl;
}
};
int main() {
Base* ptr = new Derived();
ptr->print();
delete ptr;
}
The above code will print the following:
Base::constr
Base::printImpl
Derived::constr
Derived::printImpl
but I don't understand why printImpl
private function is accessible from the base's print
function. In my understanding this
pointer implicitly passed to the print
function holds the derived object's address, but I thought private member functions could be called ONLY from the member functions (and from friend
functions) of the same class and here, Base
class is not the same class as Derived
, although there is an is a
relationship.
First, as @Eljay notes - printImpl()
is a method, albeit virtual, of the Base
class. So, it's accessible from the base class. Derived
merely provides a different implementation of it. And the whole point of virtual functions is that you can call a subclass' override using a base class reference or pointer.
In other words, private
only regards access by subclasses; it's meaningless to keep something private
from a class' base class: If a method is at all known to the base class, it must be a method of the base class... a virtual method.
Having said all that - note that the Derived
version of printImpl()
is effectively inaccessible from print()
- when it's invoked within the base class constructor. This is because during that call, the constructed vtable is only that of Base
, so printImpl
points to Base::printImpl
.
I thought private member functions could be called ONLY from the member functions of the same class
And indeed, print()
is a member of Base
, which invokes printImpl()
- another method of Base
.