1.继承
如果A是基类,B是A的派生类,那么B将继承A的数据和函数。
C++的“继承”特性可以提高程序的可复用性。正因为“继承”太有用、太容易用,才要防止乱用“继承”。我们应当给“继承”立一些使用规则。
如果类A和类B毫不相关,不可以为了使B的功能更多些而让B继承A的功能和属性。
若在逻辑上B是A的“一种”,并且A的所有功能和属性对B而言都有意义,则允许B继承A的功能和属性。
2. 组合
若在逻辑上A是B的“一部分”(a part of),则不允许B从A派生,而是要用A和其它东西组合出B。
例:
有这样一个类:
class
Eye
{
public
:
void
Look(
void
);
};
现在希望定义一个Head类,也想实现Look的功能,应该使用(组合)方法,实现代码重用。
“总结:优先使用对象组合,而不是继承”是面向对象设计的第二原则。
组合也叫“对象持有”,就是在类中定义另一类型的成员,继承会破坏类的独立性,增加系统的复杂性,一般系统的继承层次不超过3层。组合拥有良好的扩展性,支持动态组合,因此请优先考虑组合方法。
类的组合其实描述的就是在一个类里内嵌了其他类的对象作为成员的情况,它们之间的关系是一种包含与被包含的关系。简单说,一个类中有若干数据成员是其他类的对象。以前的教程中我们看到的类的数据成员都是基本数据类型的或自定义数据类型的,比如int、float类型的或结构体类型的,现在我们知道了,数据成员也可以是类类型的。
如果在一个类中内嵌了其他类的对象,那么创建这个类的对象时,其中的内嵌对象也会被自动创建。因为内嵌对象是组合类的对象的一部分,所以在构造组合类的对象时不但要对基本数据类型的成员进行初始化,还要对内嵌对象成员进行初始化。
当然,按照内嵌对象在组合类的声明中出现的次序,依次调用内嵌对象的构造函数,然后再执行本类的构造函数的函数体。
#include<iostream>
#include<cmath>
using namespace std;
class Point
{
private:
float x, y;
public:
Point(float xx, float yy)
{
cout << "point构造函数" << endl;
this->x = xx;
this->y = yy;
}
Point(Point &p)
{
x = p.x; y = p.y;
cout << "pont 拷贝构造函数" << endl;
}
float GetX(void){ return x; }
float GetY(void){ return y; }
};
class Distance
{
private:
Point p1, p2;
double dist;
public:
Distance(Point a, Point b);//构造函数
double GetDis(void){ return dist; }
};
Distance::Distance(Point a, Point b) :p1(a), p2(b)
{ //有了对象成员Point a传给p1(a), Point b传给p2(b),
//double p传给p,price=p;
double x = double(p1.GetX() - p2.GetX());
double y = double(p1.GetY() - p2.GetY());
dist = sqrt(x*x + y*y);
cout << "Distance构造函数:" << endl;
}
void main()
{
Point myp1(1, 1), myp2(4, 5);
Distance myd(myp1, myp2);
cout << "the distance is: ";
cout << myd.GetDis() << endl;
getchar();
}