继承是C++语言的一种重要机制,该机制自动地为一个类提供来自另一个类的操作和数据结构,这使得程序员只需在新类中定义已有类中没有的成分来建立新类。理解继承是理解面向对象程序设计的所有方面的关键,所以本章是很重要的。
1、继承的概念:
鸭子是鸟类的派生,鸭子是鸟类的一种,鸭子又拥有自己的特征,就是会嘎嘎叫。嘎嘎叫是区别于其他鸟类的属性。
面向对象程序设计可以让你声明一个新类作为另一个类的派生。派生类(也称为子类继承他父类的属性和操作子类也声明了新的属性和操作,剔除了那些不适合与其用途的继承下来的操作。这样继承可让你重用父类的代码,专注于为子类写新代码。)这样使我们重新使用父类代码成为可能。
继承可以使已存在的类不需修改地适应新应用,理解继承是理解面向对象程序设计所有方面的关键。
2、继承的工作方式。
|
1
2
3
4
5
6
|
class student{}class gradutestudent:public student{} |
gruduatestudent类继承了student的所有成员。集成的方式是在类定义中类名后跟:public student。一个研究生是一个学生。当然研究生类也有自己特有的成员。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
#include<iostream>#include<string>using namespace std;class Advisor//教授类{public: Advisor(); ~Advisor();private: int numofmeeting;};Advisor::Advisor(){}Advisor::~Advisor(){}class Student{public: Student(char* pname); void addcourse(int hours, float score) { average = (semesterhours + average + score);//总分 semesterhours += hours;//总修学时 average /= semesterhours;//平均分 } int gethours() { return semesterhours; } float getaverage() { return average; } void display() { cout << "name:" << name << endl; cout << "semehours:" << semesterhours << endl; cout << "averages:" << average << endl; } ~Student();private: char name[40]; int semesterhours; float average;};Student::Student(char *pname="no name"){ strncpy(name, pname, sizeof(name)); average = semesterhours = 0;}Student::~Student(){}class GraduateStudent:public Student{public: GraduateStudent(); int getqualifier() { return qualifierGrade; } ~GraduateStudent();private: Advisor advisor; int qualifierGrade;};GraduateStudent::GraduateStudent(){}GraduateStudent::~GraduateStudent(){}void main(){ Student ds("lo see undergrade"); GraduateStudent gs; ds.addcourse(3, 2.5); ds.display(); gs.addcourse(3, 3.0); gs.display(); system("pause"); return ;} |
子类的实例化对象可以做父类实例化对象能做的任何事情,拥有父类的数据成员,父类的成员函数。
3、派生类的构造:
根据类的实现机制,派生类对象创建时,将执行其默认的构造函数。该默认构造函数会首先调用基类的默认构造函数,而基类没有默认构造函数,但正好匹配默认参数的构造函数。所以在运行结果中,gs对象的name值为no name。
派生类可以直接访问基类的私有数据成员,甚至在构造时初始化他们,但是一般不这么做,而是通过基类的接口(成员函数)去访问他们,初始化也是通过基类的构造函数。
类与类之间你做你的,我做我的,以接口做沟通。即使基类与子类也不例外。这正是类能够发挥其生命力的原因所在。
在构造一个子类时,完成其基类部分的构造有积累的构造函数去做,C++类的继承机制满意的提供了这种支持。
4、继承与组合:
类以另一个类对象做数据成员,称为组合,继承与组合都发挥了重要作用,他们将以前设计好的类采用“拿来主义”,但是两者在使用上有所不同。graduatestudent是student类的一种,所以graduatestudent享有student的一切待遇。这种关系的差别,决定了操作上的差别。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
class vehicle{};class motor{};class car:public vehicle{ public: motor motor;};void vehiclefn(vehicle& v){};void motorfn(motor &m);void main(){ car c; vehiclefn(c);//ok motorfn(c);//error motorfn(c.motor);//ok} |
汽车是车辆的子类,他继承了车辆的所有特征,而汽车具有马达,如果拥有了一辆汽车,因为汽车包含有马达,所以,同时也拥有了一个马达。
5、多态性:
gaduatestudent类对象gs调用student类的成员函数display(),该函数在输出时,没办法输出graduatestudent自己的数据成员qualiciergrade。因此在使用继承时,希望重载display()。
C++允许子类重载基类的成员函数。
6、多态的思考方式:
若是语言不支持多态,则不能被称为面向对象的语言。
7、多态性如何工作:
为了指明某个成员函数具有多态性,用关键字virtual来标志其为虚函数。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
#include<iostream>#include<string>using namespace std;class Base{public: Base(); virtual void fn() { cout << "in base class" << endl;; } ~Base();private:};Base::Base(){}Base::~Base(){}class Subclass:public Base{public: Subclass(); virtual void fn() { cout << "in subclass " << endl;; } ~Subclass();private:};Subclass::Subclass(){}Subclass::~Subclass(){}void test(Base & b){ b.fn();}void main(){ Base bc; Subclass sc; cout << "calling test (bc):"; test(bc); cout << "calling test (sc):"; test(sc); system("pause"); return;} |
fn()是base类的虚函数,在test()函数中,b是基类base的传引用形参,base类对象和subclass类对象都可作为参数传递给b,所以b.fn()的调用要等到运行时,才能确认是调用基类的fn()还是子类的fn()。
由于fn()标志为虚函数,编译看见b.fn()后,将其作为迟后联编来实现。因为多态性增加了一些数据存储和执行指令的代价,所以能不多态最好。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
#include<iostream>#include<string>using namespace std;class Shape{public: Shape(double x, double y) :xcoord(x), ycoord(y) { } virtual double Area() const { return 0.0; } ~Shape();private: double xcoord; double ycoord;};Shape::~Shape(){}class Circle:public Shape{public: Circle(double x, double y, double r) :Shape(x, y), radius(r) { } virtual double Area()const { return 3.14*radius*radius; } ~Circle();private: double radius;};Circle::~Circle(){}class Rectangle:public Shape{public: Rectangle(double x1, double y1, double x2, double y2) :Shape(x1, y1), x2coord(x2), y2coord(y2){} double Rectangle::Area() const { return fabs((xcoord - x2coord)*(ycoord - y2coord)); } ~Rectangle ();private: double x2coord; double y2coord;};Rectangle ::~Rectangle (){}void fun(const Shape & sp){ cout << sp.Area() << endl;}void main(){ Circle c(2, 5, 4); fun(c); Rectangle t(2, 4, 1, 2); fun(t); system("pause"); return ;} |
多肽类让类的设计者去考虑工作的细节,而且这个细节简单到在成员函数上加一个virtual关键字。多态性使用用程序代码极大的简化,它是开启继承能力的钥匙。