派生类与继承.

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

派⽣类与继承.
⼀、引⼊继承的⽬的
1. 代码重⽤
类的继承和派⽣机制,使程序员⽆需修改已有类,只需在已有类的基础上,通过增加少量代码或修改少量代码的⽅法得到新的类,从⽽较好地解决了代码重⽤的问题。

2. 代码的扩充
只有在派⽣类中通过添加新的成员,加⼊新的功能,类的派⽣才有实际意义。

⼆、派⽣类的声明格式(单继承)
[cpp]
1. class 派⽣类名:继承⽅式基类名
2.
3. {
4.
5. //派⽣类新增的数据成员和成员函数
6.
7. };
class 派⽣类名:继承⽅式基类名
{
//派⽣类新增的数据成员和成员函数
};
1)基类名是⼀个已经定义的类的名字,也可称为⽗类;
2)派⽣类名是继承原有类的特性⽽⽣成的新类的名称;
3)继承⽅式规定了如何访问从基类继承的成员,指定了派⽣类成员以及对象对于基类继承来的成员的访问权限,它包括关键字private、protected、public(分别表⽰私有、保护、公有继承)。

4)如果不显⽰地给出继承⽅式关键字,系统默认为私有继承(private)。

三、基类成员在派⽣类中的访问属性
1. 从基类成员属性看
1)当基类成员在基类中的访问属性为private时,
在三种继承⽅式的派⽣类中的访问属性都不可直接访问;
2)当基类成员在基类中的访问属性为public时,
继承⽅式为public,在派⽣类中的访问属性为public,
继承⽅式为private,在派⽣类中的访问属性为private,
继承⽅式为protected,在派⽣类中的访问属性为protected;
3)当基类成员在基类中的访问属性为protected时,
继承⽅式为public,在派⽣类中的访问属性为protected,
继承⽅式为private,在派⽣类中的访问属性为private,
继承⽅式为protected,在派⽣类中的访问属性为protected。

基类成员在基类中访问属性
基类成员在派⽣类中访问属性public private protected
public public private protected private不可直接访问不可直接访问不可直接访问protected protected private protected
2. 从继承⽅式看
1)当继承⽅式为private时,
基类成员属性为public和protected,则在派⽣类中的访问属性为private,
基类成员属性为private,则在派⽣类中的访问属性为不可直接访问;
2)当继承⽅式为public时,
基类成员属性为public和protected,则在派⽣类中的访问属性为不变,
基类成员属性为private,则在派⽣类中的访问属性为不可直接访问;
3)当继承⽅式为protected时,
基类成员属性为public和protected,则在派⽣类中的访问属性为protected,基类成员属性为private,则在派⽣类中的访问属性为不可直接访问。

派⽣类的继承⽅式
基类成员在基类中访问属性
public private protected
public public不可直接访问protected
private private不可直接访问private
protected protected不可直接访问protected
四、派⽣类的构造函数和析构函数(单继承)
1. 说明:
1)基类的构造函数和析构函数不能被继承;
2)在派⽣类中,若对派⽣类中新增的成员进⾏初始化,就需要加⼊派⽣类的构造函数;
3)对所有从基类继承下来的成员的初始化⼯作,由基类的构造函数完成;
4)当基类含有带参数的构造函数时,派⽣类必须定义构造函数,以对基类的构造函数所需要的参数进⾏设置;
5)当基类的构造函数没有参数,或没有显式定义构造函数时(即使⽤默认构造函数),派⽣类可以不向基类传递参数,甚⾄可不定义构造函数;
6)若派⽣类的基类也是⼀个派⽣类,则每个派⽣类只需负责其直接基类的构造,⼀次上溯;
7)派⽣类与基类的析构函数是独⽴的(因为析构函数不带参数,故基类的析构函数不会因为派⽣类没有析构函数⽽得不到执⾏)。

2.构造函数和析构函数的执⾏顺序:
1)当创建派⽣类对象时,⾸先执⾏基类的构造函数,随后再执⾏派⽣类的构造函数;
2)当撤销派⽣类对象时,则先执⾏派⽣类的析构函数,随后再执⾏基类的析构函数。

例⼦:
[cpp]
1. #include <iostream.h>
2.
3. class KBase
4. {
5. public:
6. KBase() //基类的构造函数
7. {
8. cout<<"Constructing base class/n";
9. }
10.
11. ~KBase() //基类的析构函数
12. {
13. cout<<"Destructing base class/n";
14. }
15. };
16.
17. class KDerive1:public KBase
18. {
19. public:
20. KDerive1() //派⽣类1的构造函数
21. {
22. cout<<"Constructing derive1 class/n";
23. }
24.
25. ~KDerive1() //派⽣类1的析构函数
26. {
27. cout<<"Destructing derive1 class/n";
28. }
29. };
30.
31. class KDerive2:public KDerive1
32. {
33. public:
34. KDerive2() //派⽣类2的构造函数
35. {
36. cout<<"Constructing derive2 class/n";
37. }
38.
39. ~KDerive2() //派⽣类2的析构函数
40. {
41. cout<<"Destructing derive2 class/n";
42. }
43. };
44.
45. class KDerive3:public KDerive2
46. {
47. public:
48. KDerive3() //派⽣类3的构造函数
49. {
50. cout<<"Constructing derive3 class/n";
51. }
52.
53. ~KDerive3() //派⽣类3的析构函数
54. {
55. cout<<"Destructing derive3 class/n";
56. }
57. };
58.
59. int main()
60. {
61. KDerive3 obj;
62. return 0;
63. }
#include <iostream.h>
class KBase
{
public:
KBase() //基类的构造函数
{
cout<<"Constructing base class/n";
}
~KBase() //基类的析构函数
{
cout<<"Destructing base class/n";
}
};
class KDerive1:public KBase
{
public:
KDerive1() //派⽣类1的构造函数
{
cout<<"Constructing derive1 class/n";
}
~KDerive1() //派⽣类1的析构函数
{
cout<<"Destructing derive1 class/n";
}
};
class KDerive2:public KDerive1
{
public:
KDerive2() //派⽣类2的构造函数
{
cout<<"Constructing derive2 class/n";
}
~KDerive2() //派⽣类2的析构函数
{
cout<<"Destructing derive2 class/n";
}
};
class KDerive3:public KDerive2
{
public:
KDerive3() //派⽣类3的构造函数
{
cout<<"Constructing derive3 class/n";
}
~KDerive3() //派⽣类3的析构函数
{
cout<<"Destructing derive3 class/n";
}
};
int main()
{
KDerive3 obj;
return 0;
}
程序结果:
Constructing base class
Constructing derive1 class
Constructing derive2 class
Constructing derive3 class
Destructing derive3 class
Destructing derive2 class
Destructing derive1 class
Destructing base class
3. 当派⽣类中含有内嵌对象成员时,构造函数的执⾏顺序:
1)⾸先调⽤基类的构造函数,
2)其次调⽤内嵌对象成员的构造函数(有多个对象成员时,调⽤顺序由它们在类中声明的顺序确定),3)最后执⾏派⽣类的构造函数体中的内容。

4)撤销对象时,析构函数的调⽤顺序与构造函数的调⽤顺序正好相反。

4. 构造规则
4.1. 派⽣类构造函数的⼀般格式:
[cpp]
1. 派⽣类名(参数总表):基类名(参数表)
2.
3. {
4.
5. //派⽣类新增成员的初始化语句
6.
7. }
派⽣类名(参数总表):基类名(参数表)
{
//派⽣类新增成员的初始化语句
}
注:基类构造函数的参数,通常来源于派⽣类构造函数的参数总表,也可⽤常数值。

4.2. 当派⽣类中含有内嵌对象成员时,其构造函数的⼀般形式:
[cpp]
1. 派⽣类名(参数总表):基类名(参数表1),内嵌对象名1(内嵌对象参数表1),……,内嵌对象名n(内嵌对象参数表n)
2.
3. {
4.
5. //派⽣类新增成员的初始化语句
6.
7. }
派⽣类名(参数总表):基类名(参数表1),内嵌对象名1(内嵌对象参数表1),……,内嵌对象名n(内嵌对象参数表n)
{
//派⽣类新增成员的初始化语句
}
4.3. 例⼦:
[cpp]
1. #include <iostream.h>
2.
3. class KBase
4. {
5. private:
6. int x;
7. public:
8. KBase(int i)
9. {
10. x = i;
11. cout<<"Constructing base class/n";
12. }
13.
14. ~KBase()
15. {
16. cout<<"Destructing base class/n";
17. }
18.
19. void Show()
20. {
21. cout<<" x = "<<x<<endl;
22. }
23. };
24.
25. class KDerived:public KBase
26. {
27. private:
28. KBase d; //基类对象d作为派⽣类的对象成员
29. int y;
30. public:
31. //派⽣类嵌有对象成员时的构造函数格式
32. KDerived(int i, int j, int k):KBase(i),d(j)
33. {
34. y = k;
35. cout<<"Constructing derived class/n";
36. }
37.
38. ~KDerived()
39. {
40. cout<<"Destructing derived class/n";
41. }
42.
43. void Show()
44. {
45. KBase::Show();
46. d.Show();
47. cout<<" y = "<<y<<endl;
48. }
49. };
50.
51. int main()
52. {
53. KDerived obj(4,6,8);
54. obj.Show();
55. return 0;
56. }
#include <iostream.h>
class KBase
{
private:
int x;
public:
KBase(int i)
{
x = i;
cout<<"Constructing base class/n";
}
~KBase()
{
cout<<"Destructing base class/n";
}
void Show()
{
cout<<" x = "<<x<<endl;
}
};
class KDerived:public KBase
{
private:
KBase d; //基类对象d作为派⽣类的对象成员
int y;
public:
//派⽣类嵌有对象成员时的构造函数格式
KDerived(int i, int j, int k):KBase(i),d(j)
{
y = k;
cout<<"Constructing derived class/n";
}
~KDerived()
{
cout<<"Destructing derived class/n";
}
void Show()
{
KBase::Show();
d.Show();
cout<<" y = "<<y<<endl;
}
};
int main()
{
KDerived obj(4,6,8);
obj.Show();
return 0;
}
程序结果:
Constructing base class Constructing base class Constructing derived class
x = 4
x = 6
y = 8
Destructing derived class
Destructing base class
Destructing base class
五、派⽣类成员覆盖基类的同名成员
1. 含义:
在派⽣类中定义了与基类同名的成员,称为派⽣类成员覆盖基类的同名成员。

2. 在派⽣类中使⽤基类的同名成员的⽅法:
2.1 基类名::成员名;
2.2 派⽣类的对象名.基类名::成员名;
3. 例⼦:
[cpp]
1. #include <iostream.h>
2. #include <string.h>
3.
4. //类Student
5. class KStudent
6. {
7. private:
8. char *name;
9. char *stu_no;
10. float score;
11. public:
12. KStudent(char *name1, char *stu_no1, float score1);
13. ~KStudent();
14. void Show();
15. };
16.
17. KStudent::KStudent(char *name1, char *stu_no1, float score1)
18. {
19. name = new char[strlen(name1) + 1];
20. strcpy(name, name1);
21. stu_no = new char[strlen(stu_no1) + 1];
22. strcpy(stu_no, stu_no1);
23. score = score1;
24. }
25.
26. KStudent::~KStudent()
27. {
28. delete []name;
29. delete []stu_no;
30. }
31.
32. void KStudent::Show()
33. {
34. cout<<"/n name: "<<name;
35. cout<<"/n stu_no: "<<stu_no;
36. cout<<"/n score: "<<score;
37. }
38.
39. //类KUstudent
40. class KUstudent:public KStudent
41. {
42. private:
43. char *major;
44. public:
45. KUstudent(char *name1, char *stu_no1, float score1, char *major1);
46. ~KUstudent();
47. void Show(); //在派⽣类中,重新定义了成员函数Show()
48. };
49.
50. KUstudent::KUstudent(char *name1, char *stu_no1, float score1, char *major1)
51. :KStudent(name1, stu_no1, score1)
52. {
53. major = new char[strlen(major1) + 1];
54. strcpy(major, major1);
55. }
56.
57. KUstudent::~KUstudent()
58. {
59. delete []major;
60. }
61.
62. void KUstudent::Show()
63. {
64. KStudent::Show(); //定义派⽣类时,访问基类的同名成员的格式
65. cout<<"/n major: "<<major<<endl;
66. }
67.
68. int main()
69. {
70. KUstudent stu1("Liming", "990201", 90, "computer");
71. stu1.Show();
72. stu1.KStudent::Show();//派⽣类对象访问基类的同名成员的格式
73. return 0;
74. }
#include <iostream.h>
#include <string.h>
//类Student
class KStudent
{
private:
char *name;
char *stu_no;
float score;
public:
KStudent(char *name1, char *stu_no1, float score1);
~KStudent();
void Show();
};
KStudent::KStudent(char *name1, char *stu_no1, float score1)
{
name = new char[strlen(name1) + 1];
strcpy(name, name1);
stu_no = new char[strlen(stu_no1) + 1];
strcpy(stu_no, stu_no1);
score = score1;
}
KStudent::~KStudent()
{
delete []name;
delete []stu_no;
}
void KStudent::Show()
{
cout<<"/n name: "<<name;
cout<<"/n stu_no: "<<stu_no;
cout<<"/n score: "<<score;
}
//类KUstudent
class KUstudent:public KStudent
{
private:
char *major;
public:
KUstudent(char *name1, char *stu_no1, float score1, char *major1);
~KUstudent();
void Show(); //在派⽣类中,重新定义了成员函数Show()
};
KUstudent::KUstudent(char *name1, char *stu_no1, float score1, char *major1)
:KStudent(name1, stu_no1, score1)
{
major = new char[strlen(major1) + 1];
strcpy(major, major1);
}
KUstudent::~KUstudent()
{
delete []major;
}
void KUstudent::Show()
{
KStudent::Show(); //定义派⽣类时,访问基类的同名成员的格式
cout<<"/n major: "<<major<<endl;
}
int main()
{
KUstudent stu1("Liming", "990201", 90, "computer");
stu1.Show();
stu1.KStudent::Show();//派⽣类对象访问基类的同名成员的格式
return 0;
}
程序结果:
name: Liming
stu_no: 990201
score: 90
major: computer
name: Liming
stu_no: 990201
score: 90
六、访问声明
1. 格式:(在私有派⽣类的同名段中)
基类名::基类的成员函数名(或数据成员名);
2. 说明:
1)数据成员和函数成员均可使⽤访问声明;
2)访问声明的⽅法针对私有派⽣类、基类的保护成员或公有成员(不能访问基类的私有成员);
3)访问声明必须写在派⽣类定义式中的同名段中;
4)访问声明不能改变类成员原来在基类中的成员性质,只能把原基类的保护成员调整为派⽣类的保护成员,原基类的公有成员调整为派⽣类的公有成员;
5)访问声明机制可个别调整私有派⽣类从基类继承下来的成员性质,从⽽使外界可通过派⽣类的界⾯直接访问基类的某些成员,同时不影响其他基类成员的封闭性;
6)注意函数的访问声明的格式中不带返回类型和参数(既不能写出返回类型和括号);
7)对于重载函数使⽤访问声明时要慎重(因为对于基类中的重载函数名,访问声明将对基类中所有同名函数起作⽤)。

3. 例⼦:
[cpp]
1. #include <iostream.h>
2.
3. class KA
4. {
5. private:
6. int x;
7. public:
8. KA(int x1)
9. {
10. x = x1;
11. }
12.
13. void Print()
14. {
15. cout<<" x = "<<x;
16. }
17. };
18.
19. class KB:private KA
20. {
21. private:
22. int y;
23. public:
24. KB(int x1, int y1):KA(x1)
25. {
26. y = y1;
27. }
28.
29. KA::Print; //访问声明,这时Print也就成为了类KB的公有成员
30. };
31.
32. int main()
33. {
34. KB b(10,20);
35. b.Print();
36. return 0;
37. }
#include <iostream.h>
class KA
{
private:
int x;
public:
KA(int x1)
{
x = x1;
}
void Print()
{
cout<<" x = "<<x;
}
};
class KB:private KA
{
private:
int y;
public:
KB(int x1, int y1):KA(x1)
{
y = y1;
}
KA::Print; //访问声明,这时Print也就成为了类KB的公有成员
};
int main()
{
KB b(10,20);
b.Print();
return 0;
}
程序结果:x = 10
七、多重继承
1. 声明格式:
[cpp]
1. class 派⽣类名:继承⽅式1 基类名1,……,继承⽅式n 基类名n
2.
3. {
4.
5. //派⽣类新增的数据成员和成员函数
6.
7. };
class 派⽣类名:继承⽅式1 基类名1,……,继承⽅式n 基类名n
{
//派⽣类新增的数据成员和成员函数
};
2. 说明:
1)默认的继承⽅式是private;
2)在多重继承中,公有继承和私有继承对于基类成员在派⽣类中的可访问性与单继承的规则相同。

3. 构造函数和析构函数
3.1. 构造函数定义格式:
[cpp]
1. 派⽣类名(参数总表):基类名1(参数表1),基类名2(参数表2),……,基类名n(参数表n)
2.
3. {
4.
5. //派⽣类新增成员的初始化语句
6.
7. };
派⽣类名(参数总表):基类名1(参数表1),基类名2(参数表2),……,基类名n(参数表n)
{
//派⽣类新增成员的初始化语句
};
3.2. 构造函数的执⾏顺序:(与单继承构造函数的执⾏顺序相同)
1)⾸先执⾏基类的构造函数(处于同⼀层次的各个基类的构造函数的执⾏顺序,取决于声明派⽣类时所指定的各个基类的顺序,与派⽣类构造函数中所定义的成员初始化列表的各项顺序没有关系);
2)再执⾏对象成员的构造函数;
3)最后执⾏派⽣类构造函数。

4)析构函数的执⾏顺序刚好与构造函数的执⾏顺序相反。

3.3. 说明:
1)多重继承下派⽣类构造函数与单继承下派⽣类构造函数相似,它必须同时负责该派⽣类所有基类构造函数的调⽤,同时,派⽣类的参数个数必须包含完成所有基类初始化所需的参数个数;
3.4. 例⼦:
[cpp]
1. #include <iostream.h>
2.
3. class KX
4. {
5. private:
6. int a;
7. public:
8. KX(int sa)
9. {
10. a = sa;
11. cout<<"Constructing class KX/n";
12. }
13.
14. ~KX()
15. {
16. cout<<"Destructing class KX/n";
17. }
18.
19. int GetX()
20. {
21. return a;
22. }
23. };
24.
25. class KY
26. {
27. private:
28. int b;
29. public:
30. KY(int sb)
31. {
32. b = sb;
33. cout<<"Constructing class KY/n";
34. }
35.
36. ~KY()
37. {
38. cout<<"Destructing class KY/n";
39. }
40.
41. int GetY()
42. {
43. return b;
44. }
45. };
46.
47. class KZ:public KX, private KY
48. {
49. private:
50. int c;
51. public:
52. KZ(int sa, int sb):KX(sa), KY(sb)
53. {
54. c = sb;
55. cout<<"Constructing class KZ/n";
56. }
57.
58. ~KZ()
59. {
60. cout<<"Destructing class KZ/n";
61. }
62.
63. int GetZ()
64. {
65. return c;
66. }
67.
68. /*int GetY() //采⽤重载的⽅式使函数GetY()成为类KZ的公有成员
69. {
70. return KY::GetY();
71. }*/
72. KY::GetY; //采⽤访问声明的⽅式使函数GetY()成为类KZ的公有成员
73. };
74.
75. int main()
76. {
77. KZ obj(2,4);
78. int ma = obj.GetX();
79. cout<<"a = "<<ma<<endl;
80. int mb = obj.GetY();
81. cout<<"b = "<<mb<<endl;
82. int mc = obj.GetZ();
83. cout<<"c = "<<mc<<endl;
84. return 0;
85. }
#include <iostream.h>
class KX
{
private:
int a;
public:
KX(int sa)
{
a = sa;
cout<<"Constructing class KX/n";
}
~KX()
{
cout<<"Destructing class KX/n";
}
int GetX()
{
return a;
}
};
class KY
{
private:
int b;
public:
KY(int sb)
{
b = sb;
cout<<"Constructing class KY/n";
}
~KY()
{
cout<<"Destructing class KY/n";
}
int GetY()
{
return b;
}
};
class KZ:public KX, private KY
{
private:
int c;
public:
KZ(int sa, int sb):KX(sa), KY(sb)
{
c = sb;
cout<<"Constructing class KZ/n";
}
~KZ()
{
cout<<"Destructing class KZ/n";
}
int GetZ()
{
return c;
}
/*int GetY() //采⽤重载的⽅式使函数GetY()成为类KZ的公有成员
{
return KY::GetY();
}*/
KY::GetY; //采⽤访问声明的⽅式使函数GetY()成为类KZ的公有成员};
int main()
{
KZ obj(2,4);
int ma = obj.GetX();
cout<<"a = "<<ma<<endl;
int mb = obj.GetY();
cout<<"b = "<<mb<<endl;
int mc = obj.GetZ();
cout<<"c = "<<mc<<endl;
return 0;
}
程序结果:
Constructing class KX
Constructing class KY
Constructing class KZ
a = 2
b = 4
c = 4
Destructing class KZ
Destructing class KY
Destructing class KX。

相关文档
最新文档