Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is it allowed to call derived class' private virtual method via pointer of base class?

# include <iostream>
using namespace std;

class A
{
    public:
    virtual void f()
    {
        cout << "A::f()" << endl;
    }
};
class B:public A
{
    private:
    virtual void f()
    {
        cout << "B::f()" << endl;
    }
};
int main()
{
    A *ptr = new B;
    ptr->f();
    return 0;
}

This code works correctly and prints B::f(). I know how it works, but why is this code allowed?

like image 638
Mihran Hovsepyan Avatar asked Feb 14 '11 10:02

Mihran Hovsepyan


People also ask

Can a base class pointer call methods in the derived class?

Is it possible for base class pointers to call methods declared in the derived class only? No, you can only call methods that are part of the class.

Can private methods in a derived class call private methods in the base class?

Can private methods in a derived class call private methods in the base class? -Yes, if the methods are declared const in the base class.

Can base class pointer be used to call virtual function?

When you refer to a derived class object using a pointer or a reference to the base class, you can call a virtual function for that object and execute the derived class's version of the function.

Can a derived class pointer point to a base class object?

Derived class pointer cannot point to base class.


2 Answers

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.

like image 105
Steve Jessop Avatar answered Oct 16 '22 08:10

Steve Jessop


This code is allowed because f is public in A's interface. A derived class cannot change the interface of a base class. (Overriding a virtual method isn't changing the interface, nor is hiding members of a base, though both can appear to do so.) If a derived class could change a base's interface, it would violate the "is a" relationship.

If the designers of A want to make f inaccessible, then it should be marked protected or private.

like image 43
Fred Nurk Avatar answered Oct 16 '22 07:10

Fred Nurk