| I l@ve RuBoard |
| I l@ve RuBoard |
| I l@ve RuBoard |
SolutionIn my experience, many C++ programmers still seem to march to the "it isn't OO unless you inherit" battle hymn, by which I mean that they use inheritance more than necessary. See Item 24 for the whole exhausting lecture; the bottom line is simply that inheritance (including, but not limited to, IS-A) is a much stronger relationship than HAS-A or USES-A. When it comes to managing dependencies, therefore, you should always prefer composition/membership over inheritance. To paraphrase Albert Einstein: "Use as strong a relationship as necessary, but no stronger." In this code, X is derived publicly from A and privately from B. Recall that public inheritance should always model IS-A and satisfy the Liskov Substitution Principle.[2] In this case, X IS-A A and there's naught wrong with it, so we'll leave that as it is.
But did you notice the interesting thing about B? The interesting thing about B is this: B is a private base class of X, but B has no virtual functions. Now, usually, the only reason you would choose private inheritance over composition/membership is to gain access to protected members梬hich most times means "to override a virtual function."[3] As we see, B has no virtual functions, so there's probably no reason to prefer the stronger relationship of inheritance (unless X needs access to some protected function or data in B, of course, but for now I'll assume this is not the case). Assuming that is, indeed, the case, however, instead of having a base subobject of type B, X probably ought to have simply a member object of type B. Therefore, the way to further simplify the header is remove unnecessary inheritance from class B.
#include "b.h" // class B (has no virtual functions)
Because the B member object should be private (it is, after all, an implementation detail), this member should live in X's hidden pimpl_ portion. Guideline
This leaves us with vastly simplified header code. // x.h: after removing unnecessary inheritance
//
#include <iosfwd>
#include "a.h" // class A
class B;
class C;
class E;
class X : public A
{
public:
X( const C& );
B f( int, char* );
C f( int, C );
C& g( B );
E h( E );
virtual std::ostream& print( std::ostream& ) const;
private:
struct XImpl;
XImpl* pimpl_; // this now quietly includes a B
};
inline std::ostream& operator<<( std::ostream& os, const X& x )
{
return x.print(os);
}
After three passes of progressively greater simplification, the final result is that x.h is still using other class names all over the place, but clients of X need only pay for two #includes: a.h and iosfwd. What an improvement over the original! |
| I l@ve RuBoard |
本文探讨了如何通过重构类X的设计来进一步减少其头文件中的编译时依赖。通过避免不必要的继承,尤其是从没有虚函数的类B中私有派生,并采用组合的方式,实现了依赖性的最小化。
2187

被折叠的 条评论
为什么被折叠?



