第四章派生类与继承
第四章 派生类与继承 1
41派生类的概念 2 411为什么要使用继承 从现有类出发建立新的类,使新类继承老类的特点和功能,并 且又加上自己的特点和功能的程序设计方法,是面向对象程序设 计一个重要的技术。 老的类叫基类,新的类叫派生类 对派生类可做如下几种变化: (1)可以增加新的成员数据。 继承 昆虫 派生 (3)可以重新定义已有的成同酸》羽类 (2)可以增加新的成员函数。 无翅类」 (4)可以改变现有成员的属性。蛾蝇]醐蝴蝶]单一继承 C+中有两种继承: 单一继承和多重继承。 对于单一继承 窗 滚动条 派生类只能有一个基类; 对于多重继承 可滚动的窗口 派生类可以有多个基类。 多重继承
4.1 派生类的概念 4.1.1 为什么要使用继承 从现有类出发建立新的类,使新类继承老类的特点和功能,并 且又加上自己的特点和功能的程序设计方法,是面向对象程序设 计一个重要的技术。 老的类叫基类,新的类叫派生类。 对派生类可做如下几种变化: (1) 可以增加新的成员数据。 (2) 可以增加新的成员函数。 (3) 可以重新定义己有的成员函数。 (4) 可以改变现有成员的属性。 C++中有两种继承: 单一继承和多重继承。 对于单一继承 派生类只能有一个基类; 对于多重继承 派生类可以有多个基类。 昆 虫 有 翅 类 无 翅 类 蛾 苍蝇 蝴蝶 单一继承 继 承 派 生 窗 口 滚 动 条 可滚动的窗口 多重继承 2
411.为什么要使用继承? 3 class person class employee private: private: char name 10e char name 10; int age; int age; char sex: char sex; char public: department[20]; void printo; float salary; public void printo 比较二个类
4.1.1为什么要使用继承 ? class person{ private: char name[10]; int age; char sex; public: void print(); }; 比较二个类 class employee{ private: char name[10]; int age; char sex; char department[20]; float salary; public: void print(); }; 3
412派生类的声明 基类: 声明派生类 class 类名 clas派生类名:派生方式基类名 类的内容 派生类新增的数据成员和函数成员 派生方式可为公有派生用 public和私有派生(用 private或缺省) class person class employee public person i private: char name[ 10]; private: int age; char department 20; char sexs float salary; public: public: void printo; void printo;
4.1.2 派生类的声明 基类: class 类名 { 类的内容 }; 派生方式可为公有派生(用public)和私有派生(用private或缺省)。 class person{ private: char name[10]; int age; char sex; public: void print(); }; 声明派生类: class 派生类名 : 派生方式 基类名 { //派生类新增的数据成员和函数成员 }; class employee : public person { private: char department[20]; float salary; public: void print(); }; 4
1.私有派生 (1)私有派生类对基类成员的访问 基类的公有成员相当于派生类的私有成员,派生类的成员数 可以访问它。但基类的私有成员派生类的成员函数不可以访问它。 例4.1 #include void maini lass base /定义基类 int x; i derived obj public: obj setxy(10, 20) void setx(intn)x=;) void showxoi cout <<x<< end; obj showy; isoe:ph定义私有派生类 int y; public C void setxy(int n, int m i setx(n);y=m;) void showy cout<<x<y<<endl;}∥非法不能访问x,改为 show
1. 私有派生 (1) 私有派生类对基类成员的访问 基类的公有成员相当于派生类的私有成员,派生类的成员数 可以访问它。但基类的私有成员派生类的成员函数不可以访问它。 例4.1 #include class base{ //定义基类 int x; public: void setx(int n) { x=n; } void showx() { cout << x << endl; } }; class derived : private base { //定义私有派生类 int y; public: void setxy(int n, int m) { setx(n); y=m; } void showxy() { cout << x << y << endl; } // 非法 不能访问 x ,改为 showx() }; void main() { derived obj; obj.setxy(10,20); obj.showxy(); } 5
(2)外部函数(main)对私有派生类继承来的成员的访问 私有派生时,基类的所有成员在派生类中都成为私有成员,外部函 数不能访问。 例42 void main #include i derived obj; class base ∥定义基类 obj.setx(10);∥出错 int x; obj.sety(20);∥合法 public: obj. showxo;∥出错 void setx(intn)ix-n;) obj. showy;∥合法 void showxoi cout <<x < end;)) class derived: private base{∥定义私有派生类 int v: public C void sety(int n)i y=n;) void showy {cout≤<y<<endl;}
(2) 外部函数(main)对私有派生类继承来的成员的访问 私有派生时,基类的所有成员在派生类中都成为私有成员,外部函 数不能访问。 例4.2 #include class base{ //定义基类 int x; public: void setx(int n) { x=n; } void showx() { cout << x << endl; } }; class derived : private base { //定义私有派生类 int y; public: void sety(int n) { y=n; } void showy() { cout << y << endl; } }; void main() { derived obj; obj.setx(10); //出错 obj.sety(20); //合法 obj.showx(); //出错 obj.showy(); //合法 } 6
2.公有派生 7 在公有派生中,基类的私有成员对派生类来说仍是基类的私有 成员,只能通过基类的公有成员函数访问相当于可访问性保持 不变),不允许外部函数和派生类的成员函数直接访问。基类中 的公有成员相当于派生类的公有成员,外部函数和派生类的成员 函数可直接访问。 void main 例43 #include i derived obj; class baset ∥定义基类 obj.setx(10);∥合法 int x; obj.sety(20);∥合法 public: obj. showxO;∥合法 void setx(int n)ix=n; void showx0 cout <<x << endl; obJ. Showyoj ;∥合法 class derived: public base{定义公有派生类 int y; public: void sety(int n)i y=n void showy i cout <<y<< end; j
2. 公有派生 在公有派生中,基类的私有成员对派生类来说仍是基类的私有 成员,只能通过基类的公有成员函数访问(相当于可访问性保持 不变),不允许外部函数和派生类的成员函数直接访问。基类中 的公有成员相当于派生类的公有成员,外部函数和派生类的成员 函数可直接访问。 例4.3 #include class base{ //定义基类 int x; public: void setx(int n) { x=n; } void showx() { cout << x << endl; } }; class derived : public base {//定义公有派生类 int y; public: void sety(int n) { y=n; } void showy() { cout << y << endl; } }; void main() { derived obj; obj.setx(10); //合法 obj.sety(20); //合法 obj.showx(); //合法 obj.showy(); //合法 } 7
在作类派生时,可能导致几个类使用同一函数名或变量名,这 就会产生二义性。 如 class x{ public: int f0; #include void maino (Xa class Y: public i public: int fO; int i-a f0; int g0 int j=b f0; cout <<i"<<i<< endl cout <<j=<<j<< endl; 这里bfO用的是Y类的fO还是X类的f0?用的是Y类的 fO,编译器会自动从继承底向上搜索,这叫作支配规则。如果一 定要用X类的fO,则可写成bX:f0;X:叫作用域分辨符
在作类派生时,可能导致几个类使用同一函数名或变量名,这 就会产生二义性。 如 class X { public: int f(); }; class Y : public X { public: int f(); int g(); }; 这里 b.f() 用的是Y 类的 f() 还是 X 类的 f()? 用的是Y 类的 f(),编译器会自动从继承底向上搜索,这叫作支配规则。如果一 定要用 X 类的 f(),则可写成 b.X::f(); X::叫作用域分辨符。 #include void main( ) { X a; Y b; int i=a.f(); int j=b.f(); cout << "i=" << i << endl; cout << "j=" << j << endl; } 8
表4.1公有派生和私有派生的访问特性 基类成员 基类私有成员 基类公有成员 基类保护成员 派生方式 private| public private| public private public 派生类成员|不可访问不可访问可访问可访问可访问可访问 外部函数不可访问不可访问不可访问可访问不可访问不可访问
表4.1公有派生和私有派生的访问特性 基类成员 基类私有成员 基类公有成员 基类保护成员 派生方式 private public private public private public 派生类成员 外部函数 不可访问 不可访问 不可访问 不可访问 可访问 不可访问 可访问 可访问 可访问 不可访问 可访问 不可访问 9
41.3基类的保护成员作用 无论私有派生还是公有派生,派生类无权访问它的基类的私有 成员。派生类要想访问它的基类的私有成员,只能通过调用基类 的成员函数的方式实现,对这有时会带来不便。C十十还提供 种访问属性 protected保护性成员。基类的保护成员具有私有成 员和公有成员双重角色:对自已的对象而言它是私有成员,即不 能被其他程序或函数访问(只能被类中的成员函数访问);而对派 生类而言,它又相当于是基类的公有成员。当公有派生时,基类 的保护成员在派生类也为保护成员。当私有派生时,相当于派生 类的私有成员,派生类的成员函数可以访问它
4.1.3 基类的保护成员作用 无论私有派生还是公有派生,派生类无权访问它的基类的私有 成员。派生类要想访问它的基类的私有成员,只能通过调用基类 的成员函数的方式实现,对这有时会带来不便。C++还提供一 种访问属性protected 保护性成员。基类的保护成员具有私有成 员和公有成员双重角色:对自已的对象而言它是私有成员,即不 能被其他程序或函数访问(只能被类中的成员函数访问);而对派 生类而言,它又相当于是基类的公有成员。当公有派生时,基类 的保护成员在派生类也为保护成员。当私有派生时,相当于派生 类的私有成员,派生类的成员函数可以访问它。 10