整个c++程序设计全面围绕面向对象的方式进行,类的继承特性是c++的一个非常非常重要的机制,继承特性可以使一个新类获得其父类的操作和数据结构,程序员只需在新类中增加原有类中没有的成分。下面我们简单的来说一下继承的概念,先看下图:
上图是一个抽象描述的特性继承表
交通工具是一个基类(也称做父类),通常情况下所有交通工具所共同具备的特性是速度与额定载人的数量,但按照生活常规,我们来继续给交通工具来细分类的时候,我们会分别想到有汽车类和飞机类等等,汽车类和飞类同样具备速度和额定载人数量这样的特性,而这些特性是所有交通工具所共有的,那么当建立汽车类和飞机类的时候我们无需再定义基类已经有的数据成员,而只需要描述汽车类和飞机类所特有的特性即可,飞机类和汽车类的特性是由在交通工具类原有特性基础上增加而来的,那么飞机类和汽车类就是交通工具类的派生类(也称做子类)。以此类推,层层递增,这种子类获得父类特性的概念就是继承。
下面我们根据上图的理解,有如下的代码:
#include <iostream> using namespace std; class Vehicle { public: void EditSC(float speed,int total); protected: float speed;//速度 int total;//最大载人量 }; void Vehicle::EditSC(float speed,int total) { Vehicle::speed = speed; Vehicle::total = total; } class Car:public Vehicle//Car类继承Vehicle的特性,Car类是Vehicle的派生类 { public: Car() { aird=0; } protected: int aird;//排量 }; class plane:public Vehicle { protected: float wingspan;//翼展 }; void main() { Car a; a.EditSC(150,4); cin.get(); }
派生类的定义可以在类名称后加冒号public空格加基类名称进行定义,如上面代码中的class Car:public Vehicle。 一旦成功定义派生类,那么派生类就可以操作基类的所有数据成员包括是受保护型的,上面代码中的a.EditSC 就是例子,甚至我们可以在构造派生类对象的时候初始化他们,但我们是不推荐这么做的,因为类于类之间的操作是通过接口进行勾通的,为了不破坏类的这种封专装特性,即使是父类于子类的操作也应按遵循这个思想,这么做的好处也是显而易见的,当基类有错的时候,只要不涉及接口,那么基类的修改就不会影响到派生类的操作。
下面我们来说一下,派生类对象(子类对象)的构造。 由上面的例程我们知道Car是Vehicle类的派生类,c+规定,创建派生类对象的时候首先调用基类的构造函数初始化基类成员,随后才调用派生类构造函数。 但是要注意的是,在创建派生类对象之前,系统首先确定派生类对象的覆盖范围,上面代码的派生类对象a就覆盖于Vehicle类和Car类上,至于派生类对象的创建是如何构造基类成员的,我们看如下代码,随后再进行分析:
#include <iostream> using namespace std; class Vehicle { public: Vehicle(float speed=0,int total=0) { cout<<"载入Vehicle类构造函数"<<endl; Vehicle::speed = speed; Vehicle::total = total; } Vehicle(Vehicle &temp) { Vehicle::speed = temp.speed; Vehicle::total = temp.total; } ~Vehicle() { cout<<"载入Vehicle类析构函数"<<endl; cin.get(); } protected: float speed;//速度 int total;//最大载人量 }; class Car:public Vehicle { public: Car(float aird=0,float speed = 0,int total = 0):Vehicle(speed,total) { cout<<"载入Car类构造函数"<<endl; Car::aird = aird; } Car(Car &temp):Vehicle(temp.speed,temp.total) { cout<<"载入Car类拷贝构造函数"<<endl; Car::aird = temp.aird; } ~Car() { cout<<"载入Car类析构函数"<<endl; cin.get(); } protected: float aird;//排量 }; void main() { Car a(250,150,4); Car b = a; cin.get(); }
对象a创建的时候通过Car(float aird = 0,float speed = 0,int total = 0):Vehicle(speed,total),也就是Car类构造函数,来构造Car类对象成员,但按照c++的规定首先应该调用基类构造函数构造基成员,在这里基类成员的构造是通过Vehicle(speed,total),来实现的。但值得注意的是Vehicle(speed,total)的意义并不是对Vehicle类的个个成员的初始化,事实上是利用它创建了一个Vehicle类的无名对象,由于Car类对象的覆盖范围是覆盖于Vehicle类和Car类上,所以系统在确定了派生类对象a的空间范围后,确定了this指针位置,这个this指针指向了Vehicle类的那个无名对象,这个成员赋值过程就是,this->speed=无名对象.speed。
C++类的继承特性