c++编程实现:
一个Point类,然后一个Circle类,继承Point类。circle类能够实现求圆的面积,移动圆的位置,改变圆的大小。
基于实际应用的考虑:
Circle派生自Point,乍一想圆缩小到最后不就是个点嘛,这个还算合情合理。但是当圆遇到圆心时问题就出现了。
A Circle is not a Point. It is implemented in terms of Points。
Point类的成员变量容易确定,即X坐标和Y坐标,然而Circle类的圆心也是Point,该做何处理?
1)如果Circle以父类的成员变量作为圆心的坐标,显然圆心与圆的关系使用Composition更好。
2)将Point的成员变量设为private,Circle在继承Point的同时,包含一个Point的成员变量表示圆心。但这样还费劲继承干吗,不如直接Composition。
实现:
暂且抛开点派生圆的合理性问题,让我们从上面第1种实现出发,看看需要注意哪些内容:
1) Point类的两个成员变量最好声明为protected,以便Circle在必要时进行修改。
2) Point类的析构函数定义为虚函数,以防止当Circle对象被Point指针析构时,子类数据没有被析构掉。
3) PI的定义,既然是C++了,最好就不要用C形式的#define,我这里采用的方式是static const成员变量,当然也可以定义一个const全局变量。
4)求圆的面积和改变圆的大小只能在Circle类中实现,因为Point没有这两项需求。
而移动圆的位置,最好实现在Point类中,首先这是Point类本身的需要,而对于Circle类来说,移动圆的位置等同于移动圆心的位置。
5) 出于性能考虑,可以适当将成员变量声明为inline函数,定义在类里面的函数本身就是内联的。出于泛化考虑,可以使用模板类,将X和Y坐标以及半径的数据类型声明为模板参数。
代码如下:
-
- template <typename T>
- class Point
- {
- public:
- Point()
- { }
- Point(const T& x, const T& y)
- : _x(x)
- , _y(y)
- { }
- Point(const Point<T>& pt)
- : _x(pt._x)
- , _y(pt._y)
- { }
- virtual ~Point()
- { }
- public:
- void SetX(const T& x)
- {
- _x = x;
- }
- void SetY(const T& y)
- {
- _y = y;
- }
- T GetX()
- {
- return _x;
- }
- T GetY()
- {
- return _y;
- }
- virtual void SetPosition(const T& x, const T& y)
- {
- _x = x;
- _y = y;
- }
- protected:
- T _x;
- T _y;
- };
- template<typename T, typename U>
- class Circle : public Point<T>
- {
- public:
- Circle() : Point<T>()
- { }
- Circle(const T& x, const T& y, const U& radius)
- : Point<T>(x, y)
- , _radius(radius)
- { }
- Circle(const Circle<T, U>& rcCcl)
- : Point<T> (rcCcl._x,rcCcl._y)
- , _radius(rcCcl._radius)
- { }
- ~Circle()
- { }
- public:
- void SetRadius(const U& radius)
- {
- _radius = radius;
- }
- U GetRadius()
- {
- return _radius;
- }
- U GetArea()
- {
- return _pi* _radius * _radius;
- }
- private:
- U _radius;
- static const double _pi;
- };
- template <typename T, typename U>
- const double Circle<T,U>::_pi = 3.14159;