Why would a virtual function be private?

2019-01-21 10:56发布

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)

8条回答
成全新的幸福
2楼-- · 2019-01-21 11:35

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);
};

查看更多
淡お忘
3楼-- · 2019-01-21 11:35

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.

查看更多
虎瘦雄心在
4楼-- · 2019-01-21 11:37

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.

查看更多
相关推荐>>
5楼-- · 2019-01-21 11:47

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.

查看更多
霸刀☆藐视天下
6楼-- · 2019-01-21 11:47

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.

查看更多
等我变得足够好
7楼-- · 2019-01-21 11:54

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,

查看更多
登录 后发表回答