Question

e.g.

// Implementation.
struct PrivatePoint {
  void SomePrivateMethod();

  double x;
  double y;
}

struct Point : private PrivatePoint {
  double DistanceTo(const Point& other) const;
}

This seems similar to the Pimpl idiom. This has two advantages that I really like:

  1. SomePrivateMethod is testable. If SomePrivateMethod were instead declared as private in Point, you wouldn't be able to call it from tests. If you declared it as public or protected in Point, tests would be able to call it, but so would regular users of Point.
  2. Accessing private data is easier to read and write compared to how you'd do it in the Pimpl idiom, because you don't have to go through a pointer e.g.

.

Point::DistanceTo(const Point& other) {
  SomePrivateMethod();

  double dx = other.x - x;
  double dy = other.y - y;
  return sqrt(dx * dx + dy * dy);
}

vs.

Point::DistanceTo(const Point& other) {
  ptr->SomePrivateMethod();

  double dx = other.ptr->x - ptr->x;
  double dy = other.ptr->y - ptr->y;
  return sqrt(dx * dx + dy * dy);
}
Was it helpful?

Solution

Your suggestion has some drawbacks....

The users may couple themselves to the "private" class.

The pimpl idiom's primary purpose is as a compilation firewall, allowing the private members to be specified in the implementation file, and therefore to be changed without touching the header and necessitating / triggering client recompilation, as distinct from just relinking, which is faster, and may not even require any actions involving the client app if the update is to a dynamically loaded library. You lose these benefits.

SomePrivateMethod is testable. If SomePrivateMethod were instead declared as private in Point, you wouldn't be able to call it from tests. If you declared it as public or protected in Point, tests would be able to call it, but so would regular users of Point.

There are other convenient if hackish options: for example - you can declare friendship with testing code, or use the preprocessor to build in a testing mode that exposes data.

OTHER TIPS

Private inheritance is very similar to composition (and pimpl) but has some drawbacks to consider:

  1. You need to make PrivatePoint definition visible in a public header. This introduces compile time dependency on PrivatePoint and requires clients of Point to recompile every time PrivatePoint is changed. With pimpl this is not the case, it is enough to forward declare PrivatePoint like this: struct PrivatePoint;

  2. Enapsulation is weeker. With private inheritance, clients that extend Point are be able to implement their own version of SomePrivateMethod (C++ allows to overwrite private virtual methods). This is not a problem in your example, but would be if SomePrivateMethod was declared virtual

If you used pimpl, you could also easily unit test PrivatePoint.

no, as anyway you have to publish header file that declares the base class. the private inheritance protect you or your users from unwanted access to the data/methods.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top