I have been reading an article about C++ interfaces (http://accu.org/index.php/journals/233) and I am completely lost at the part where it says all the virtual member functions should be made private (the section titled "Strengthening the Separation"). It just does not make sense to me at all.
According to the author, the code is like this:
class shape {
public:
virtual ~shape();
virtual void move_x(distance x) = 0;
virtual void move_y(distance y) = 0;
virtual void rotate(angle rotation) = 0;
//...
};
class line : public shape {
public:
line(point end_point_1, point end_point_2);
//...
private:
virtual ~line();
virtual void move_x(distance x);
virtual void move_y(distance y);
virtual void rotate(angle rotation);
//...
};
So we have a pure virtual function which is public, and its implementation (in the line class) which is private.
Could anybody explain how the move_x function can be called? Its access specifier is private, it will lead to an error if I try to do this:
line my_line(point(0,0), point(1,2));
my_line.move_x(-1); // does not compile
Similarly is it correct to say that the drawing interface (see earlier in the article)cannot access these functions either?
Thank you.
The idea is that you'd use those methods via a reference or pointer to shape
.
shape &s = my_line;
s.move_x(-1);
This could be justified on the grounds of "reveal only what you need to", or as a form of self-documentation. It proves that the methods are only called in the intended way.
If you have in instance of the line
object, you might be tempted to call it's methods. But if the only way you can get at them is by asking for it's shape
interface, then the object looks to less like an object and more like a collection of interfaces.
This makes more sense if you imagine line implementing more than one interface.
This advice is applicable to homogeneous hierarchies only -- that is, hierarchies in which derived classes introduce no new functions (except constructors maybe) and just override base class functions. In this case you obviously don't need to work with line
instance directly -- only via pointer/reference to shape
.
When you have less homogeneous hierarchy, this advice hasn't much sense: how would anyone apply it to cases when derived class introduces new functions, or inherits them from another base class? In this case you sometimes want to work directly with objects of derived class directly, and this advice would lead to inconveniences only.
Further development of this idea -- less radical and usable in more contexts -- Non-Virtual Interface (NVI) by Herb Sutter.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With