questions about an article introducing C++ interface
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 d开发者_运维问答rawing 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.
I think that the article highlights the rationale well in this quote:
Now, the only thing users can do with line is create instances of it. All usage must be via its interface - i.e. shape, thus enforcing a stronger interface/implementation separation. Before leaving this topic, it is important to get something straight: the point of enforcing the interface/implementation separation is not to tell users what to do. Rather, the objective is to underpin the logical separation - the code now explains that the key abstraction is shape, and that line serves to provide an implementation of shape.
That is, line
is not by itself interesting. It's just an implementation of the shape
interface, and there may be other implementations. You're particularly interested in the shape
interface. Hence, you should only access the implementation through this interface, and not as a standalone class.
精彩评论