首先我们看这样一道题目:
Shape类,其中有getArea、getPerimeter、getVolume和getName函数。
Point类继承Shape类,包括:私有数据成员x、y,构造函数,get/set函数和show函数,还有一个计算与其他点之间距离的函数double distance(const Point &p)。
Circle类继承Point类,包括:私有数据成员radius,构造函数,get/set函数和show函数,隐藏了基类的getArea、getPerimeter、getName函数。
Cylinder类继承Circle类,包括:私有数据成员height,构造函数,get/set函数和show函数,隐藏了基类的getArea、getVolume和getName函数。
Triangle类继承Shape类,包括:私有成员对象point1、point2和point3,构造函数和show函数,隐藏了基类的getArea、getPerimeter、getName函数。
在main函数中测试Point、Circle、Cylinder和Triangle类。
要完成这个代码要充分理解继承与派生含义与以下几个含义:
1.公有继承:当类的继承方式为公有继承时,基类的公有成员和保护成员的访问属性在派生类中不变,而基类的私有成员不可直接访问。也就是说基类的公有成员和保护成员被继承到派生类中访问属性不变,仍作为派生类的公有成员和保护成员,派生类的其他成员可以直接访问它们。在类族之外只能通过派生类的对象访问从基类继承的公有成员,而无论是派生类的成员还是派生类的对象都无法直接访问基类的私有成员。
2.同名隐藏:如果派生类声明了一个和某基类成数据或函数同名的成员员同名的新成员(如果是成员函数,则参数表也要相同,参数不同的情况属于重载)、派生的新成员就隐藏了外层同名成员。这时在派生类中或者通过派生类的对象,直接使用成员名就只能访问到派生类中声明的同名成员,这称做同名隐藏。
3.构造函数:派生类的成员对象是由所有基类的成员对象与派生类新增的成员对象共同组成。因此构造派生类的对象时,就要对基类的成员对象和新增成员对象进行初始化构造函数并没有继承下来,要完成这些工作,就必须给派生类添加新的相莫毋题。派生类 基类的对于基类的很多成员对象是不能直接访问的,因此要完成对基类成员对象的初始化工作,需要通过调用基类的构造函数。派生类的构造函数需要以合适的初值作为参数,其中一些参数要传递给基类的构造函数,用于初始化相应的成员,另一些参数要用于对派生类新增的成员对象进行初始化。在构造派生类的对象时,会首先调用基类的构造函数,来初始化它们的数据成员,然后按照构造函数初始化列表中指定的方式初始化派生类新增的成员对象,然后才执行派生类构造函数的函数体。
UML类图:
代码解析:
//各个类的代码
class shape
{
public:
shape(){}
~shape(){}
double getArea();
double getPerimeter();
double getVolume();
string getName();
};
class Point:public shape
{
public:
Point(){}
~Point(){}
Point(int a, int b);
int getx() {return x;}
int gety() {return y;}
void setpoint(int a,int b);
void show();
double distance(const Point &p);
private:
int x;
int y;
};
class circle :public Point
{
public:
circle() {};
~circle(){}
circle(int a,int b,double r);
double getcircle() { return radius; }
void setcircle(int a, int b, double ra);
double getArea();
double getPerimeter();
string getName();
void show();
private:
double radius;
};
class cylinder:public circle
{
public:
cylinder(){}
~cylinder(){}
cylinder(int a, int b, double ra, int c);
int getcylinder() { return height; }
void setcylinder(int a, int b, double ra,int c);
void show();
double getArea();
double getVolume();
string getName();
private:
int height;
};
class Triangle : public shape
{
public:
Triangle(){}
~Triangle(){}
Triangle(Point a, Point b, Point c);
void show();
double getArea();
double getPerimeter();
string getName();
private:
Point point1;
Point point2;
Point point3;
};
//源代码CPP:
//两点之间距离求解:
double Point::distance(const Point &p)
{
int m;
m = p.x*p.x + p.y*p.y;
double n;
n = sqrt(m);
return n;
}
circle::circle(int a,int b,double r)
{
cout << "此为circle构造函数调用!" << endl<<"圆心";
setpoint(a, b);
radius = r;
cout << endl;
}
//圆面积:
double circle::getArea()
{
return 3.14*radius*radius;
}
//圆周长:
double circle::getPerimeter()
{
return 2 * 3.14*radius;
}
得到名字:
string circle::getName()
{
return "circle";
}
Cylinder函数实现
void circle::setcircle(int a, int b, double ra)
{
setpoint(a, b);
radius = ra;
cout << "radius:" << ra << endl;
}
cylinder::cylinder(int a, int b, double ra, int c)
{
cout << "此为cylinder构造函数调用" << endl<<"圆心";
setcircle(a, b, ra);
height = c;
cout << endl;
}
void cylinder::setcylinder(int a, int b, double ra, int c)
{
setcircle(a, b, ra);
height = c;
cout << "height:" <<height<< endl;
}
void cylinder::show()
{
cout << "height:" << height << endl;
}
double cylinder::getArea()
{
double n = getcircle();
double m;
m = 2 * 3.14*n*n + 2 * 3.14*n*height;
return m;
}
double cylinder::getVolume()
{
double n = getcircle();
double m;
m = 3.14*n*n*height;
return m;
}
string cylinder::getName()
{
return "cylinder";
}
Triangle函数实现
Triangle::Triangle(Point a, Point b, Point c)
{
point1 = a;
point2 = b;
point3 = c;
}
void Triangle::show()
{
cout << "triangle的三点为:" << endl;
point1.show();
point2.show();
point2.show();
}
double Triangle::getArea()
{
int x1 = point1.getx();
int y1 = point1.gety();
int x2 = point2.getx();
int y2 = point2.gety();
int x3 = point3.getx();
int y3 = point3.gety();
double m;
m = (x1*y2 - x1*y3 + x2*y3 - x2*y1 + x3*y1 - x3*y2)/2;
return m;
}
double Triangle::getPerimeter()
{
int x1 = point1.getx();
int y1 = point1.gety();
int x2 = point2.getx();
int y2 = point2.gety();
int x3 = point3.getx();
int y3 = point3.gety();
double n1 = sqrt((x2 - x1)*(x2 - x1)+(y2-y1)*(y2-y1));
double n2 = sqrt((x3 - x2)*(x3 - x2)+(y3-y2)*(y3-y2));
double n3 = sqrt((x3 - x1)*(x3 - x1) + (y3 - y1)*(y3 - y1));
double m = n1 + n2 + n3;
return m;
}
string Triangle::getName()
{
return "triangle";
}
运行结果:
总结:
类继承中,派生类包含了它所有基类的除构造、析构函数之外的所有成员。对基类成员的改造包括两个方面,第一个是基类成员的访问控制问题,依靠派生类定义时的继承方式来控制。第二个是对基类数据或函数成员的隐藏,对基类的功能进行改造。派生类新成员的加入是继承与派生机制的核心,是保证派生类在功能上有所发展的关键。清楚类之间关系很重要也是难点。
参考书籍:面向对象程序设计