继承性是OOP中最重要的特征,可以说,如果没有掌握继承性,就等于没有掌握类和对象的精华,就是没有掌握OOP的真谛。因为OOP强调的是软件的可重用性。
那么,继承这么重要,他到底是什么呢?
在C++中·,所谓的继承就是在一个已经存在类的基础上建立一个新类。比如,马是一个父类,那么他诞生的公马就是在他的基础上,加了一个性别属性。那么他诞生的是一个白公马,那么白公马就是公马的继承,然后又多加了颜色这个属性。所以,一个新类从已有的类中获得其已有的属性,这种现象就是继承。通过继承,一个新建的子类从已有的父类哪里获得父类的属性。从另一个角度说,从已有的类产生的新的子类,称为类的派生。类的继承是用已有的类来建立专用类的技术。派生类继承了基类的所有数据成员和成员函数,并可以对成员做必要的增加或调整。一个基类可以派生出多种类,每个派生类,又可以作为基类再派生出新的类,因此基类和派生类是相对而言的。
他可以有两种情况:1.一个派生类是从一个基类中派生出的,称为单继承。2,.一个派生类是从两个或两个以上继承而来的那么就称为多重继承
同样,继承也可以分成三种情况:1.公有继承2.私有继承3.保护继承
派生类的构成:1.从基类继承过来的(体现了派生类从基类继承获得的特性)2.自己增加的(体现了派生类的个性)
下面我们来说公有继承:
先说如何声明一个类是派生类。class Student :public person。这就是公有继承的方式,class 后的是派生类的名字。后面必须跟上“:”这个符号,然后写上继承的方式,“public,private,protected”之后就是基类的名字。然后是,公有继承的访问属性:1.基类的成员函数可以访问基类的数据成员,派生类的成员函数可以访问派生类成员,基类的成员函数不能访问派生类的成员。2.私有成员只能被同一类的函数访问,公有函数可以被外界访问。3.公有继承,基类的公用成员和保护成员在派生类中保持原有的访问属性,其私有成员仍为基类私有。所以·,派生类的成员函数不能访问基类的私有成员,基类的私有成员只能被基类的成员函数访问。还有就是,在继承时,无法继承基类的构造函数和析构函数
所以如果我们在使用时需要从新定义构造函数,否则报错;
下面我们就使用一个具体的例子来说明它:这是关于点与点,点与线的关系
Point类功能:
(1) 移动一个点;
(2) 显示一个点;
(3) 可计算这个点到原点的距离。
Line类功能:
(1) 计算点到直线的距离;
(2) 直线的斜率;
(3) 判断两条直线的关系(平行/相交(交点坐标能够给出来并显示)/垂直);
#include<iostream>
#include<cmath>
using namespace std;
class Point
{
public:
Point();
Point(double abs,double ord):m_abs(abs),m_ord(ord){}
double shift_abs()
{
cout<<"请输入您想将这一个点移动到"<<endl;
cout<<"横坐标:";
cin>>m_abs;
return m_abs;
}
double shift_ord()
{
cout<<"请输入您想将这一个点移动到"<<endl;
cout<<"纵坐标:";
cin>>m_ord;
return m_ord;
}
void show()
{
cout<<"("<<m_abs<<","<<m_ord<<")"<<endl;
}
void length()
{
double m;
m=sqrt(m_abs*m_abs+m_ord*m_ord);
cout<<"到原点的距离是"<<m<<endl;
}
double m_abs;//横坐标
double m_ord;//纵坐标
};
class Line:public Point
{
public:
Line(double abs,double ord):Point(abs,ord){}
void length1()
{
//点1(n1,n2),点2(n3,n4),点3(n5,n6)
cout<<"点一"<<endl;
double n1=shift_abs();
double n2=shift_ord();
cout<<"点二"<<endl;
double n3=shift_abs();
double n4=shift_ord();
cout<<"点三"<<endl;
double n5=shift_abs();
double n6=shift_ord();
//点1,到直线点二 点三 的距离
double k=(n6-n4)/(n5-n3);
double k1;
double k2;
k1=n6-n5*k;
cout<<"直线方程:"<<k<<"x"<<"+"<<k1<<"-y"<<"=0"<<endl;
cout<<"点1 到直线的距离为:";
k2=(k*n1+k1-n2)/(sqrt(k*k+1));
cout<<k2<<endl;
cout<<endl;
}
void ascent()
{
cout<<"点一"<<endl;
double n1=shift_abs();
double n2=shift_ord();
cout<<"点二"<<endl;
double n3=shift_abs();
double n4=shift_ord();
double k=(n4-n2)/(n3-n1);
cout<<"由点一和点二形成的直线的斜率是:"<<k<<endl;
}
void m_relation()
{
cout<<"点一"<<endl;
double n1=shift_abs();
double n2=shift_ord();
cout<<"点二"<<endl;
double n3=shift_abs();
double n4=shift_ord();
cout<<"点三"<<endl;
double n5=shift_abs();
double n6=shift_ord();
cout<<"点四"<<endl;
double n7=shift_abs();
double n8=shift_ord();
cout<<"由点一和点二形成直线,由点三和点四形成的直线"<<endl;
double k=(n4-n2)/(n3-n1);
double k1=(n8-n6)/(n7-n5);
if(k==k1)
{
cout<<"两直线平行"<<endl;
}
else if(k*k1==-1)
{
cout<<"两直线垂直"<<endl;
}
else
{
cout<<"两直线相交"<<endl;
double b=n2-k*n1;
double b1=n6-k1*n5;
double x=(b1-b)/(k-k1);
double y;
y=k*x+b;
cout<<"两直线相交于一点该点的坐标是:("<<x<<","<<y<<")"<<endl;
}
}
};
int main()
{
cout<<"========点与点的关系========"<<endl;
cout<<endl;
Point p(0,0);
cout<<"起始坐标:";
p.show();
p.shift_abs();
p.shift_ord();
cout<<"移动后的坐标";
p.show();
p.length();
cout<<"=====点与线,线与线的关系====="<<endl;
cout<<endl;
Line l(0,0);
l.length1();
l.ascent();
l.m_relation();
return 0;
}
由代码可以看出Line类是由Point类继承而来的,由于线是由点构成的,所以Point类是关于点的可以被Line类使用。
特别注意的就是:
基类的构造函数:Point(double abs,double ord):m_abs(abs),m_ord(ord){}
派生类的构造函数:Line(double abs,double ord):Point(abs,ord){}
所以,需要两个构造函数,而且他们是不同的。
这样我们就比较了解,继承的用意了,如果没有继承那么Line类还需要去定义Point中的成员函数和数据成员;