Hedede
Hedede

Reputation: 1173

Private overriden virtual functions in derived class

Is there any point to making virtual member functions, overridden from a base class private, if those are public in the base class?

struct base {
    virtual void a();
};

struct derived : base {
// ...
private:
    void a() override;
};

Upvotes: 4

Views: 109

Answers (4)

Gem Taylor
Gem Taylor

Reputation: 5613

If you are forced to do a 2-phase construction on the implementation class (i.e. have an init() method as well as or instead of a constructor that has to be called (I know, but there are reasons), then this stops you calling any /other/ methods directly on the instance pointer before you pass it back as an interface pointer. Go the extra mile, make the inheritance private, and have your one public init function return the interface pointer!

Another reason is you just don't /need/ to write public: in a final implementation class declaration, so then by default everything is private. But why you would do that and use struct instead of class I don't know. Perhaps this was converted from class at some point due to a style war?

Upvotes: 1

ALX23z
ALX23z

Reputation: 4703

Yes, if you inherit the base class as private. Otherwise, it is more of a weird explicit-like restriction - user has to has to make an explicit conversion to use the function - it is generally ill advised as few will be able to comprehend the author's intention.

If you want to restrict some functions from base class, make a private/protected inheritance and via using keyword declare which base-methods you want to be protected/public in the derived class.

Upvotes: 1

p-a-o-l-o
p-a-o-l-o

Reputation: 10047

Looking at your design, I see one cannot call derived::a directly, but only through a base interface.

Is there any point? Consider that, once we have a derived instance, we can always up-cast to its base, so given

derived d;

while d.a() wouldn't compile, we can always do

base & b = d;
b.a(); //which actually calls derived::a

In other words: derived::a is not that private, after all, and I would discourage this design, which can be confusing to the user.

Things change if the members private in derived are private in base, as well: this time it is clear that they just cannot be called directly, outside base or derived.

Let's say we have a couple of functions, and want them to be called conditionally, according to a value passed as an argument to a third one:

struct base 
{
    void dosomething(bool x)
    {
        if(x)
        {
            do_this();
        }
        else
        {
            do_that();
        }
    }
private:
    virtual void do_this(){}
    virtual void do_that(){}
};

Thus a derived class could be like:

struct derived : base 
{
private:
    void do_this() override { }
    void do_that() override { }
};

and no other class can call them, unless it extended base itself:

derived d;
d.dosomething(true); //will call do_this() in derived
d.dosomething(false); //will call do_that() in derived

d.do_that() //won't compile

Upvotes: 1

463035818_is_not_an_ai
463035818_is_not_an_ai

Reputation: 122133

The same reasoning as for non-virtual methods applies: If only the class itself is supposed to call it make it private.

Consider the template method pattern:

struct base {
    void foo() { a() ; b(); }
    virtual void a() = 0;
    virtual void b() = 0;
};

struct derived : base {
private:
    void a() override {}
    void b() override {}
};
int main()
{
   derived().foo();
}

Perhaps a and b should have been protected, but anyhow the derived can change accesibility and it requires some documentation so that derived knows how it is supposed to implement a and b.

Upvotes: 0

Related Questions