第四章派生类与继承
第四章 派生类与继承 1
41派生类的概念 411为什么要使用继承 从现有类出发建立新的类,使新类继承老类的特点和功能,并 且又加上自己的特点和功能的程序设计方法,是面向对象程序设 计一个重要的技术。 老的类叫基类,新的类叫派生类 对派生类可做如下几种变化: 继承 昆虫 (1)可以增加新的成员数据。 派生 (2)可以增加新的成员函数。 有翅类 无翅类 (3)可以重新定义己有的成员函数打 (4)可以改变现有成员的属性。匚蛾靥蝇蝴蝶]单一继承 C++中有两种继承 单一继承和多重继承。 对于单一继承 滚动条」 派生类只能有一个基类; 对于多重继承 可滚动的窗口 派生类可以有多个基类。 多重继承
4.1 派生类的概念 4.1.1 为什么要使用继承 从现有类出发建立新的类,使新类继承老类的特点和功能,并 且又加上自己的特点和功能的程序设计方法,是面向对象程序设 计一个重要的技术。 老的类叫基类,新的类叫派生类。 对派生类可做如下几种变化: (1) 可以增加新的成员数据。 (2) 可以增加新的成员函数。 (3) 可以重新定义己有的成员函数。 (4) 可以改变现有成员的属性。 C++中有两种继承: 单一继承和多重继承。 对于单一继承 派生类只能有一个基类; 对于多重继承 派生类可以有多个基类。 昆 虫 有 翅 类 无 翅 类 蛾 苍蝇 蝴蝶 单一继承 继 承 派 生 窗 口 滚 动 条 可滚动的窗口 多重继承 2
411.什么要使用继承? class person( class employee private private char name[101 char name[101 Int age; int age; char sex: char sex char public department 20: void printo float salary; public void print(; 比较二个类
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类名 class 派生类名:派生方式基类名 类的内容 /派生类新增的数据成员和函数成员 派生方式可为公有派生(用 public)和私有派生(用 private或缺省)。 class persont class employee: public person i private: char name[ 10l; p rivate. int age; char department 20 char sex 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)私有派生类对基类成员的访问 基类的公有成员相当于派生类的私有成员,派生类的成员数 可以访问它。但基类的私有成员派生类的成员函数不可以访问它。 例41 #include void maino class baset 定义基类 int x; i derived obj; public obj. setxy(10, 20) void setx( int n)ix-n; void showxoi cout <<x<< endl obj. showy; class derived: private base定义私有派生类 int public void setxy(int n, int m i setx(o);y=m;) void showy cout<<x<y<endl;}∥非法不能访问x,改为 show0
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
()外部函数(main)对私有派生类继承来的成员的访问 私有派生时,基类的所有成员在派生类中都成为私有成员,外部函 数不能访问。 例42 void maino #include i derived obj; class baset ∥定义基类 obj. setx((10);∥出错 Int x; 0bety(20);∥合法 public obj. showxO;∥出错 void setx(int n)x=n;) obj. showy;∥合法 void showxoi cout <<x<< end; class derived: private base{/定义私有派生类 nt y; public void sety(int n)i void showy {cout≤<y<end;}
(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.公有派生 在公有派生中,基类的私有成员对派生类来说仍是基类的私有 成员,只能通过基类的公有成员函数访问(相当于可访问性保持 不变),不允许外部函数和派生类的成员函数直接访问。基类中 的公有成员相当于派生类的公有成员,外部函数和派生类的成员 函数可直接访问。 例43 void maino #include i derived obj lass base ∥定义基类 Int x; obj. setx((10);∥合法 public obj. sety(20);∥合法 void setx (intn)xen; obj. showN;∥合法 void show(0{ cout <<x<< endl;} obj. showy;∥合法 }; lass derived: public base i定义公有派生k C int y public void sety(int n)i y=n; 3 void showy {cout≤<y<end;}
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{ 8 #include public: int f0; void main( Xa class y: publica i Ybs public: int fO int i=a int go it j=bfO cout <<i="<<i<< endl; cout <<j=<<j<< endl 这里bf(用的是Y类的f0还是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
413基类的保护成员作用 无论私有派生还是公有派生,派生类无权访问它的基类的私有 成员。派生类要想访问它的基类的私有成员,只能通过调用基类 的成员函数的方式实现,对这有时会带来不便。C十+还提供 种访问属性 protected保护性成员。基类的保护成员具有私有成 员和公有成员双重角色:对自已的对象而言它是私有成员,即不 能被其他程序或函数访问(只能被类中的成员函数访问);而对派 生类而言,它又相当于是基类的公有成员。当公有派生时,基类 的保护成员在派生类也为保护成员。当私有派生时,相当于派生 类的私有成员,派生类的成员函数可以访问它
4.1.3 基类的保护成员作用 无论私有派生还是公有派生,派生类无权访问它的基类的私有 成员。派生类要想访问它的基类的私有成员,只能通过调用基类 的成员函数的方式实现,对这有时会带来不便。C++还提供一 种访问属性protected 保护性成员。基类的保护成员具有私有成 员和公有成员双重角色:对自已的对象而言它是私有成员,即不 能被其他程序或函数访问(只能被类中的成员函数访问);而对派 生类而言,它又相当于是基类的公有成员。当公有派生时,基类 的保护成员在派生类也为保护成员。当私有派生时,相当于派生 类的私有成员,派生类的成员函数可以访问它。 10