Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Private method in a C++ interface?

Tags:

c++

Why would I want to define a C++ interface that contains private methods?

Even in the case where the methods in the public scope will technically suppose to act like template methods that use the private methods upon the interface implementation, even so, we're telling the technical specs. right from the interface.

Isn't this a deviation from the original usage of an interface, ie a public contract between the outside and the interior?

You could also define a friend class, which will make use of some private methods from our class, and so force implementation through the interface. This could be an argument.

What other arguments are for defining a private methods within an interface in C++?

like image 516
gavri Avatar asked Jul 22 '10 08:07

gavri


2 Answers

The common OO view is that an interface establishes a single contract that defines how objects that conform to that interface are used and how they behave. The NVI idiom or pattern, I never know when one becomes the other, proposes a change in that mentality by dividing the interface into two separate contracts:

  • how the interface is to be used
  • what deriving classes must offer

This is in some sense particular to C++ (in fact to any language with multiple inheritance), where the interface can in fact contain code that adapts from the outer interface --how users see me-- and the inner interface --how I am implemented.

This can be useful in different cases, first when the behavior is common but can be parametrized in only specific ways, with a common algorithm skeleton. Then the algorithm can be implemented in the base class and the extension points in derived elements. In languages without multiple inheritance this has to be implemented by splitting into a class that implements the algorithm based in some parameters that comply with a different 'private' interface. I am using here 'private' in the sense that only your class will use that interface.

The second common usage is that by using the NVI idiom, it is simple to instrument the code by only modifying at the base level:

class Base {
public:
   void foo() { 
      foo_impl();
   }
private:
   virtual void foo_impl() = 0;
};

The extra cost of having to write the dispatcher foo() { foo_impl(); } is rather small and it allows you to later add a locking mechanism if you convert the code into a multithreaded application, add logging to each call, or a timer to verify how much different implementations take in each function... Since the actual method that is implemented in derived classes is private at this level, you are guaranteed that all polymorphic calls can be instrumented at a single point: the base (this does not block extending classes from making foo_impl public thought)

void Base::foo() {
   scoped_log log( "calling foo" ); // we can add traces
   lock l(mutex);                   // thread safety
   foo_impl();
}

If the virtual methods were public, then you could not intercept all calls to the methods and would have to add that logging and thread safety to all the derived classes that implement the interface.

like image 128
David Rodríguez - dribeas Avatar answered Oct 24 '22 02:10

David Rodríguez - dribeas


You can declare a private virtual method whose purpose is to be derivated. Example :

class CharacterDrawer {
public:
   virtual ~CharacterDrawer() = 0;

   // draws the character after calling getPosition(), getAnimation(), etc.
   void  draw(GraphicsContext&);

   // other methods
   void  setLightPosition(const Vector&);

   enum Animation {
      ...
   };

private:
   virtual Vector getPosition() = 0;
   virtual Quaternion getRotation() = 0;
   virtual Animation getAnimation() = 0;
   virtual float getAnimationPercent() = 0;
};

This object can provide drawing utility for a character, but has to be derivated by an object which provides movement, animation handling, etc.

The advantage of doing like this instead of provinding "setPosition", "setAnimation", etc. is that you don't have to "push" the value at each frame, instead you "pull" it.

I think this can be considered as an interface since these methods have nothing to do with actual implementation of all the drawing-related stuff.

like image 3
Tomaka17 Avatar answered Oct 24 '22 03:10

Tomaka17