Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Herb Sutter's article on making virtual functions private

I read Herb Sutter's article http://www.gotw.ca/publications/mill18.htm on virtual functions and how they should be declared private by default. Making a virtual function public would make it serve as an interface and customizer, and the suggestion is to separate the interfacing from the customization behavior, as the article suggests.

class shape
{
  protected:
    void set_area(double area)
    {
      area = area;
    };
  private:
    double area;
    virtual void compute_area() = 0;
};
class square
{

  private:
    double length;
    void compute_area()
    {
      set_area(length*length);
    }
};

If we consider these classes, we see that we can never call the area function from outside of either class because they are made to be virtual since we don't want the virtual function to serve as the interface between the class and the "outside world" as Sutter suggested. If I understand him correctly, to use the template method, and if I want to compute the area on a shape object, I'd need to provide a public non-virtual function to shape class. So something like this?

class shape
{
  public:
    void interfacer()
    {
      compute_area();
    }
  protected:
    void set_area(double area)
    {
      area = area;
    };
  private:
    double area;
    virtual void compute_area() = 0;
}

Doesn't that seem redundant over being able to just simply do:

shape *ptr = new square();
ptr->compute_area(); 

if we were to make the virtual function public?

I reread the article and he said the public virtuals should be "Rarely if ever" used. I wonder if he would think the above is one of those instances where it'd be appropriate to make the virtual function public instead of private.

like image 827
24n8 Avatar asked Oct 18 '25 07:10

24n8


1 Answers

You understood correctly. You have to provide a public non-virtual function that calls the virtual function.

You seem to be asking what is the point of this: why have users call a public function that calls the private implementation rather than just having one function that does the work? Herb answers this in the post:

First, note that the base class is now in complete control of its interface and policy, and can enforce interface preconditions and postconditions, insert instrumentation, and do any similar work all in a single convenient reusable place - the nonvirtual interface function. ...

Second, when we've better separated interface and implementation, we're free to make each take the form it naturally wants to take instead of trying to find a compromise that forces them to look the same. For example, ...

Third, the base class is now less fragile in the face of change. We are free to change our minds later and add pre- and postcondition checking, or separate processing into more steps, or refactor, or implement a fuller interface/implementation separation using the Pimpl idiom[4], or make other modifications to Widget's customizability, without affecting the code that uses Widget. ...

In general, many of the benefits of writing properly factored code only become truly apparent when it comes time to make the code more complex.

like image 73
Brian Bi Avatar answered Oct 20 '25 20:10

Brian Bi