Why C++ Overriding Rules Ignore Visibility Changes

clanguage-designobject-oriented

In C++, it is possible to write an overriding for a base class's method even if the visibility declaration of the two don't match.
What are the possible design considerations under the decision of not considering the visibility in the overriding rule?

Consider this piece of code as an example:

class A{
    public: virtual void f() { cout << "A::f" << endl; }
};

class B : public A {
    private: void f() { cout << "B::f" << endl; }
};

int main() {
    A* a = new B;
    a->f();
}

The above compiles in clang, and running it prints B::f, showing that it is possible to call a private function of B from outside the class, thus breaking encapsulation.

I don't really see why this type of behavior should be allowed. It is clearly not for performance/efficiency reasons, since checking statically that two visibility declarations match is trivial. Does anybody have an idea or hypothesis about what could possibly be the design decision behind this?

Best Answer

The above compiles in clang, and running it prints B::f, showing that it is possible to call a private function of B from outside the class, thus breaking encapsulation.

The encapsulation isn't broken. It's B that's semi-broken. B publicly inherits from A. A's public interface is B's public interface. The real question is why B should be permitted to even create a private override of a public function.

Simple fact is, there's just no real reason to ban it. If you're writing B and do so correctly, this should never happen in reality. Unless you explicitly intended it for some reason, in which case, congratulations.