Search code examples
c++virtual-functionsaccess-specifier

When should you restrict accessibility to a virtual function in a derived class?


Consider the following code:

class Base
{
public:
    virtual void Foo() {}
};

class Derived : public Base
{
private:
    void Foo() {}
};

void func()
{
    Base* a = new Derived;
    a->Foo(); //fine, calls Derived::Foo()

    Derived* b = new Derived;
//  b->Foo(); //error
    static_cast<Base*>(b)->Foo(); //fine, calls Derived::Foo()
}

I've heard two different schools of thought on the matter:

  1. Leave accessibility the same as the base class, since users could use static_cast<Derived*> to gain access anyway.

  2. Make functions as private as possible. If users require a->Foo() but not b->Foo(), then Derived::Foo should be private. It can always be made public if and when that's required.

Is there a reason to prefer one or the other?


Solution

  • Restricting access to a member in a subtype breaks the Liskov substitution principle (the L in SOLID). I would advice against it in general.

    Update: It may "work," as in the code compiles and runs and produces the expected output, but if you are hiding a member your intention is probably making the subtype less general than the original. This is what breaks the principle. If instead your intention is to clean up the subtype interface by leaving only what's interesting to the user of the API, go ahead and do it.