Private virtual method in C ++

What is the advantage of creating a private virtual method in C ++?

I noticed this in an open source C ++ project:

class HTMLDocument : public Document, public CachedResourceClient { private: virtual bool childAllowed(Node*); virtual PassRefPtr<Element> createElement(const AtomicString& tagName, ExceptionCode&); }; 
+81
c ++ polymorphism access-specifier
Jan 31 '10 at 5:39
source share
5 answers

Herb Sutter explained it very well here .

Guideline 2: Preference to make virtual functions private.

This allows derived classes to redefine a function to customize behavior as needed, without further directly mapping virtual functions, making them callable derived classes (as would be possible if functions were simply protected). The fact is that there are virtual functions to configure; if they also should not be called directly from the code of derived classes, there is no need to ever do anything other than private

+91
Jan 31 '10 at 5:42
source share

If the method is virtual, it can be overridden by derived classes, even if it is private. When a virtual method is called, an overridden version is called.

(In contrast to Herb Sutter, cited by Prasun Sauraw in his answer, the C ++ FAQ Lite recommends against private virtual machines , mainly because he often confuses people.)

+54
Jan 31 '10 at 5:46
source share

Despite all the calls to declare the virtual member private, the argument simply does not contain water. Often, overriding a derived class of a virtual function must invoke a version of the base class. It cannot if private declared:

 class Base { private: int m_data; virtual void cleanup() { /*do something*/ } protected: Base(int idata): m_data (idata) {} public: int data() const { return m_data; } void set_data (int ndata) { m_data = ndata; cleanup(); } }; class Derived: public Base { private: void cleanup() override { // do other stuff Base::cleanup(); // nope, can't do it } public: Derived (int idata): base(idata) {} }; 

You must declare the base class method protected and indicate that the method should be overridden, but not called.

 class Base { ... protected: // chained virtual function! // call in your derived version but nowhere else. // Use set_data instead virtual void cleanup() { /* do something */ } ... 

So Herb Sutter guideline # 3 ... But the horse still gets out of the barn.

When you declare something protected , you implicitly trust the writer of any derived class to understand and correctly use the protected internal components, as a way of declaring friend implies a deeper trust for private members.

Users who misbehave violate this trust (for example, are marked as "ignorant" without bothering to read your documentation) themselves are to blame.

Update . I had some feedback stating that you can β€œchain” the implementation of virtual functions in this way using private virtual functions. If so, I would like to see it.

The C ++ compilers I use will definitely not allow a derived class implementation to invoke a private base class implementation.

If the C ++ committee relaxed "private" to allow this particular access, I would be all for private virtual functions. In its current form, we are still advised to lock the barn door after the horse has been stolen.

+8
Feb 25 '16 at 16:00
source share

I first came across this concept while reading Scott Myers Effective C ++, paragraph 35: Consider Alternatives to Virtual Functions. I wanted to contact Scott Myers for others who might be interested.

This is part of the template method template through the idiom of a non-virtual interface: public access methods are not virtual; rather, they wrap virtual method calls that are private. The base class can run logic before and after calling a private virtual function:

 public: void NonVirtualCalc(...) { // Setup PrivateVirtualCalcCall(...); // Clean up } 

I think this is a very interesting design template, and I'm sure you can see how the added control is useful.

  • Why create a virtual private function? The best reason is that we have already provided the public method.
  • Why not just make it protected so that I can use this method for other interesting things? I believe that this will always depend on your design and how you think the base class is suitable. I would say that the creator of a derived class should focus on implementing the necessary logic; everything else will already be taken care of. In addition, there is a question about encapsulation.

From a C ++ point of view, it is completely legal to redefine a private virtual method, even if you cannot call it from your class. This supports the design described above.

+4
Jun 11 '14 at 19:58
source share

I use them to allow derived classes to "fill in the blanks" for the base class without exposing such a hole to end users. For example, I have objects with a high degree of objectivity, based on a common base, which can only implement 2/3 of the general state of the machine (derived classes provide the remaining 1/3 depending on the template argument, and the base cannot be a template for other reasons) .

I NEED to have a common base class to make many of the public APIs work correctly (I use variational templates), but I cannot let this object go into the wild. Even worse, if I leave the craters in the state machine - in the form of pure virtual functions - anywhere, but in "Private", I allow a smart or ignorant user to receive from one of their child classes an override of methods that users should never touch. So, I put the "brains" of the machine into the virtual functions of the PRIVATE. Then the immediate children of the base class fill in the gaps in their N-virtual overrides, and users can safely use the resulting objects or create their own additional derived classes without worrying about running the state machine.

Regarding the argument that you should not have public virtual methods, I say BS. Users can inappropriately redefine private virtual machines as easily as regular ones, because they still define new classes. If the publication should not modify this API, do not make it virtual AT ALL in public objects.

+2
Feb 05 '14 at 21:10
source share



All Articles