Access control is performed at compile time, not runtime. There's no way in general for the call to f()
to know the runtime type of the object pointed to by ptr
, so there's no check on the derived class's access specifiers. That's why the call is permitted.
As for why class B is permitted to override using a private function at all - I'm not sure. Certainly B violates the interface implied by its inheritance from A, but in general the C++ language doesn't always enforce inheritance of interface, so the fact that it's Just Plain Wrong doesn't mean C++ will stop you.
So I'd guess that there's probably some use case for this class B - substitution still works with dynamic polymorphism, but statically B is not a substitute for A (e.g. there can be templates that call f
, that would work with A as argument but not with B as argument). There may be situations where that's exactly what you want. Of course it could just be an unintended consequence of some other consideration.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…