由于类别继承和物件组合是物件导向软体设计的两个主要方法?r在不便使用继承的场合里?o常使用物件组合?o此时也常用委托观念。 物件A 把外界传来的讯息\" 转送\" 给物件B ?o由B 处理之?o我们称物件A 委托物件B 。当一群物件互相沟通分工合作时常用妥托观念。虽然C++ 并未直接支援委托功能?o但能间接地表达出来。由于类别继承(Class Inheritance) 和物件组合(Object Composition)是物件导向软体设计的两个主要方法?r在不便使用继承的场合里?o常使用物件组合?o此时也常用委托观念。例如?o有个\" 长方形\" 类别?s 接着想设计个\" 正方形\" 类别?o大多数人会先想到继承功能?s 如此就可重复使用(Reuse)这 Area()函数了。 这个继承结构有些美中不足之处?o例如Square从Rectangle 继承了SetWidth()及SetHeight() 函数?o对Square()而言是无用而且有害。万一呼叫到Square的SetWidth()?o则Square的4 边就不等长了?u这时?o可改用物件组合方式来代替继承?s 当Square之物件接到外界传来的Area()讯息时?o就委托Rectangle 之物件代为处理。以C++ 表达如下?s //// Rectangle //// class Rectangle { double width, height; public: void SetWidth(double w) { width=w; } void SetHeight(double h) { height=h; } double Area() { return width*height; } }; class Square { Rectangle *rectangle; public: Square() { rectangle = new Rectangle; } void SetLength(double len) { rectangle->SetWidth(len); rectangle->SetHeight(len); } double Area() { return rectangle->Area(); } }; SetWidth()及SetHeight() 不属于Square类别?o就无上述的副作用了。但也些缺点?srectangle 值是在程式执行时才确定的?o也就是委托关系是在执行时才建立起来。一旦rectangle 值改变了?o就改变委托的对象。所以委托是很有弹性的,但却常令程式更复杂。反过来,继承关系是在程式编译时就确定了?o能使程式较清楚?o但在执行时无法改变继承关系?o弹性较小。因之?o继承和委托皆能达到重复使用(Reuse)之目的?o各有所长各有所短?o相辅相成才是完美的。简单规则是?s 「优先考虑使用继承?o若觉得牵强?o 就考虑用委托」 请看下述例子?o有个\" 圆形\" 类别以及\" 正方形\" 类别?o共同衍生出CR类别?s CR类别的Draw()会先呼叫Square::Draw()绘出正方形?o再呼叫Circle::Draw()绘出正方形的内接圆。以C++ 表示为?s //// Circle //// class Circle { protected: int x, y, r; public: Circle(int a, int b, int) :x(a), y(b), z(c) {} void Draw() { .... } }; //// Square //// class Square { public: virtual int GetX()=0; virtual int GetY()=0; virtual int GetLength()=0; void Draw() { GetX() GetY() .... } }; //// class CR //// class CR : public Circle, public Square { public: virtual int GetX() { return x; } virtual int GetY() < |