Why would a virtual function be private?
Asked Answered
R

7

27

I just spotted this in some code:

class Foo {
[...]
private:
    virtual void Bar() = 0;
[...]
}

Does this have any purpose?

(I am trying to port some code from VS to G++, and this caught my attention)

Rizzio answered 15/7, 2009 at 20:49 Comment(8)
I'm sorry, what part confuses you exactly?Medlar
The "private" part.Rizzio
I don't know if people are upvoting the previous comment because it sounds comical or because they are confused as well...Sectarianism
The question makes sense to me, though maybe it's because I misunderstand some other concepts. If a subclass can't access/override a private function, and that private function is virtual... how does it ever get used?Eschalot
Does this answer your question? Private virtual method in C++Tiny
@DonaldDuck, if anything, that other question is answered by the answers here.Rizzio
@Rizzio They're duplicates, so they both answer each other. Since the other question and its answers have a higher score, it's better to close this one as a duplicate.Tiny
Yet this one attracted much better quality answers.Rizzio
N
10

This is a pure virtual function that happens to be private. This makes it so that a derived class must implement the method. In this case Bar.

I think you may be confused b/c this is done to create "interfaces" in C++ and a lot of times people think of these as public. There are cases where you may want to define an interface that is private where a public method uses those private methods in order to ensure the order of how they are called. (I believe this is called the Template Method)

For a relatively bad example :)

class RecordFile
{
    public:
       RecordFile(const std::string &filename);

       void process(const Record &rec)
       {
           // Call the derived class function to filter out
           // records the derived instance of this class does
           // not care about
           if (filterRecord(rec))    
           {
               writeRecordToFile(rec);           
           }
       };

    private:
       // Returns true if the record is of importance
       // and should be kept
       virtual bool filterRecord(const Record &rec) = 0;

       void writeRecordToFile(const Record &rec);
};

Notus answered 15/7, 2009 at 21:12 Comment(6)
I don't get it, because private methods are not visible in derived classes. How can a derived class override a method that it cannot "see", or call, or access in any way?Parshall
+1 - You've given practical reasons for Herb Sutter's argument.Couchant
Abelenky, you've pointed out the primary source of confusion regarding private virtuals, but the fact is that you don't have to be able to call a function to be able to define it. This lets the base class tell its descendants, "Provide me a function, but I alone shall decide when to call it."Perform
FYI, you're missing a semicolon after the ending brace on the class declaration. ;)Violative
@RobKennedy I wish your comment was posted/accepted as an answer, since it's the clearest, most concise explanation of what's actually happening. None of the answers explains it nearly as well.Eschalot
@RobKennedy I completely agree with dwanderson. This is the real explanation of the confusion, the "how", though the Sutter article is the bigger picture of the "why" it is being done.Arabist
E
10

ISO C++ 2003 explicitly allows it:

§10.3 states nothing about access specifier and contains even a footnote in the second clause stating in the context of virtual function overrides:

[...] Access control (clause 11) is not considered in determining overriding.

The code is fully legal.

Why is this useful?

Generally, you want to have a clear entry point into your class hierarchy by introducing a public non-virtual function which calls the virtual function then. This is called a Non Virtual Interface idiom or NVI. And the non-virtual function can be implemented as inline function.

class Foo {
public:
[...]
    void bar() {
        bar_impl();
    }
private:
    virtual void bar_impl() = 0;
[...]
}


class FooImpl1 : public Foo {
   ...
   void bar_impl() override {
      // ... do something here
   }
}

class FooImpl2 : public Foo {
   ...
   void bar_impl() override {
      // ... do something here
   }
}    
std::unique_ptr<Foo> foo = std::make_unique<FooImpl2>{};
foo->bar();

So far so good... Now you realize you have a bunch of classes which implement Foo and you need to debug bar_impl(). You have a choice: putting a breakpoint in every single bar_impl() because you don't know what object type has been created, or you can put the breakpoint into the non-virtual caller function bar and step into the bar_impl() from there. Furthermore, you can implement some logging in bar() which is then called before and after all potential bar_impl() calls or you can use a lock before bar_impl() and introduce thread-safety for the entire hierarchy and so on...

Why using a private virtual function instead of protected?

Std IOStreams use NVI with protected virtual functions. Merely it's about how you want your users to reuse the functionality. With protected virtual function the derived type is able to call the virtual function of the base type. This might be a good or bad idea depending on the virtual function's side effects. For example, both base and derived virtual functions try to acquire a non-reentrant lock and end up in a deadlock. I generally, tend to write private virtual functions to avoid such surprises and have clear responsibilities in the program. I know it can confuse new C++ developers, but that's not that hard to explain why this design is more advantageous. And actually, I was a novice in C++ as well and got it explained... Some more explanations on private virtual functions: https://isocpp.org/wiki/faq/strange-inheritance#private-virtuals

Extract answered 15/7, 2009 at 21:28 Comment(0)
I
7

I'm going to quote a brief explanation from the great C++ FAQ Lite which sums it up well:

[23.4] When should someone use private virtuals?

Almost never.

Protected virtuals are okay, but private virtuals are usually a net loss. Reason: private virtuals confuse new C++ programmers, and confusion increases cost, delays schedule, and degrades risk.

New C++ programmers get confused by private virtuals because they think a private virtual cannot be overridden. After all, a derived class cannot access members that are private in its base class so how, they ask, could it override a private virtual from its base class? There are explanations for the above, but that's academic. The real issue is that almost everyone gets confused the first time they run into private virtuals, and confusion is bad.

Unless there is a compelling reason to the contrary, avoid private virtuals.


The C++ FAQ Lite was updated in the meantime:

By the way, it confuses most novice C++ programmers that private virtuals can be overridden, let alone are valid at all. We were all taught that private members in a base class are not accessible in classes derived from it, which is correct. However this inaccessibility by the derived class does not have anything to do with the virtual call mechanism, which is to the derived class. Since that might confuse novices, the C++ FAQ formerly recommended using protected virtuals rather than private virtuals. However the private virtual approach is now common enough that confusion of novices is less of a concern.

Instantaneous answered 15/7, 2009 at 20:58 Comment(6)
I think Cline and Sutter disagree here. See the link in Greg Rogers' answer.Vagrancy
This is why I dislike the C++ FAQ, its full of opinions that are sometime just silly, and goes against best practices as defined by some of the leading thinkers in the field. See Herb Sutters answer for a much better explanation that has the opisite opinion.Sadirah
The standard stream library is also a great place to see examples of private virtual funcitons with public non virutal that use them.Sadirah
-1: Many things confuse new C++ programmers. Do we discourage them from using such things. No, of course not because if we did that they would stay new C++ programmers. What a load of nonsense.Ecclesia
@Martin Agree strongly. Lots of things the FAQ says make me grind my teeth! But I suppose it's better than nothing.Halfpint
I probably agree with all the comments made here, I wasn't aware of it's 'real' usage before. But I think that to the people the C++ FAQ is directed at, the answer it provides is good. The thing it's probably missing is a reference to Sutter's article rather than saying it's useless.Instantaneous
B
7

The usual "academic" answer is: access specifiers and virtuality are orthogonal - one does not affect the other.

A little more practical answer: private virtual functions are often used to implement the Template Method design pattern. In languages that do not support private virtual functions, the template method needs to be public although it is not really meant to be a part of the interface.

Baroscope answered 15/7, 2009 at 21:12 Comment(3)
If access specifiers and virtuality are orthogonal then why ideone.com/JjbVOP fails in compilation? Virtual function call is resolved at runtime not compile time then what I did wrong in my program? Isn't it possible to override protected virtual methods of Base class by Derived class ?Saum
@Saum That compilation error is because you're trying to call a protected method of Parent from main().Spouse
"In languages that do not support private virtual functions, the template method needs to be public ..." -- Do you mean the virtual method needs to be public?Adjudicate
A
2

It is a pure virtual function. Any final implementation that is dervied from "Foo" MUST implement the "Bar" function.

Amby answered 15/7, 2009 at 20:52 Comment(1)
except it is marked as 'private'. The OP did not make his question clear, and I had to look at it for a second or two before I realized it was marked as private, so +1 to negate the -1.Ftc
L
1

It makes the function pure virtual as opposed to virtual.

No implementation is provided by default and the intent is that the function implementation must be specified by an inheriting class. This can be overriden however.

You sometimes see complete classes where all member functions are specified as pure virtual in this manner.

These are Abstract Base Classes, sometimes referred to as Interface Classes, and the designer of the ABC is saying to you, "I have now idea how this functionality would be implemented for all specialisations of this base class. But, you must have all of these defined for your specialisation to work and you know how your object should behave".

Edit: Oops, just spotted the fact that the member pure virtual function is private. (Thanks Michael) This changes things slightly.

When this base class is inherited using private inheritance it changes things. Basically what the designer of the base class is doing is saying is that, when your derived class calls a non-private function in the base class. part of the behaviour has been delegated to your specialisation of the function in your derived class. The non-private member is doing "something" and part of that "something" is a call, via the pure virtual base class function, to your implementation.

So some public function in Foo is calling the Bar function inside Foo, and it is relying on the fact that you will provide a specialised implementation of the Bar function for your particular case.

Scott Meyers refers to this as "implemented in terms of".

BTW Just chuckling about the number of answers that were quickly deleted by people who also didn't see the "fine print" in the question! (-:

HTH

cheers,

Larentia answered 15/7, 2009 at 20:52 Comment(0)
U
0

The only purpose it seems to serve is to provide a common interface.

BTW even though a function is declared as private virtual, it can still be implemented and called with the class instance or from friends.

Nonetheless, this sort of things usually meant to serve as interface, yet I don't do it this way.

Unsuspecting answered 15/7, 2009 at 20:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.