第7章 继承性和派生类
派生类与继承.
派⽣类与继承.⼀、引⼊继承的⽬的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 protectedpublic public private protected private不可直接访问不可直接访问不可直接访问protected protected private protected2. 从继承⽅式看1)当继承⽅式为private时,基类成员属性为public和protected,则在派⽣类中的访问属性为private,基类成员属性为private,则在派⽣类中的访问属性为不可直接访问;2)当继承⽅式为public时,基类成员属性为public和protected,则在派⽣类中的访问属性为不变,基类成员属性为private,则在派⽣类中的访问属性为不可直接访问;3)当继承⽅式为protected时,基类成员属性为public和protected,则在派⽣类中的访问属性为protected,基类成员属性为private,则在派⽣类中的访问属性为不可直接访问。
C++ 第7章 继承2
class Vehicle {//...}; class Motor {//...}; class Car : public Vehicle { public: Motor motor; }; void vehicleFn(Vehiccle& v); void motorFn(Motor& m); void main( ) { Car c; vehicleFn(c); //ok motorFn(c); //error motorFn(c.motor); //ok }
23
7-1-4 类的分解及抽象类
声明一个函数是纯虚函数的语法,即让C++知 道该函数无定义,在Account类中示例如 下:
class Account { public: Account(unsigned accNo,float balan=0.0); int AccountNo(); float AcntBalan(); static Account * First(); Account* Next(); Static int NoAccounts(); void Display(); void Deposit{float amount}; virtual void Withdrawal(floa tamount)=0; //纯虚函数 protected: static Account* pFirst; Account* pNext(); static int count; unsigned acntNumber; float balance; };
24
7-1-4 类的分解和抽象类
一个抽象类不能有实例对象,即不能由该类抽象 来制造一个对象。所以,下面的声明是非法的:
Visual C++继承性与派生类
继承性与派生类9.1 继承性与派生类的基本概念继承是软件复用的一种形式,它是从现有类的基础上建立新类,新类继承了现有类的属性和方法,并且还拥有其特有的属性和方法。
继承的过程称为派生,新建的类为派生类(或子类),原有的类称为基类(或父类)。
继承可分为:单继承和多重继承。
若派生类只有一个基类则称为单继承;若派生类有多个基类则称为多重继承。
9.2 派生类的声明与访问权限9.2.1 派生类的声明单继承中派生类的定义格式为:class <派生类名>:<派生方式><基类名>{派生类新定义的成员声明;};说明:①派生方式关键字为private、public和protected,分别表示私有继承、公有继承和保护继承。
缺省的继承方式是私有继承。
继承方式规定了派生类成员和类外对象访问基类成员的权限。
②派生类新定义的成员是指继承过程中新增加的数据成员和成员函数。
通过在派生类中新增加成员实现功能的扩充。
9.2.2 派生类的访问权限公有继承(public)①继承后基类的公有成员、私有成员、保护成员在派生类中访问权限保持不变。
②在派生类中可以直接访问基类的公有成员和保护成员,但对于私有成员的访问只能通过基类的非私有成员函数间接访问。
③在基类和派生类定义以外只能通过派生类的对象访问基类的公有成员,无法通过派生类对象直接访问基类的私有成员和保护成员。
私有继承(private)①继承后基类的所有成员在派生类中均为私有成员。
②在派生类中可以直接访问基类的公有成员和保护成员,但对于私有成员的访问只能通过基类的非私有成员函数间接访问。
③在基类和派生类定义以外对基类的所有成员均无法直接访问也无法通过派生类的对象间接访问。
保护继承(protected)①继承后基类的公有成员和保护成员在派生类中均为保护成员,基类的私有成员在派生类中仍为私有成员。
②在派生类中可以直接访问基类的公有成员和保护成员,但对于私有成员的访问只能通过基类的非私有成员函数间接访问。
继承和派生的作用
继承和派生的作用继承和派生是面向对象编程中常用的两个概念,它们在软件开发中起着重要的作用。
继承是指一个类从另一个类继承属性和方法的过程,派生是指在继承的基础上创建新的类的过程。
本文将分别介绍继承和派生的作用。
一、继承的作用1. 代码复用:通过继承,子类可以继承父类的属性和方法,避免了重复编写相同代码的麻烦。
这样可以提高代码的复用性,减少了代码量,提高了开发效率。
2. 继承关系的表达:通过继承,可以清晰地表达类与类之间的关系。
子类继承了父类的属性和方法,说明它们之间有某种联系,有共同的特征或行为。
3. 扩展功能:通过继承,子类可以在父类的基础上新增或修改属性和方法,实现功能的扩展。
这样可以满足不同的需求,增加了代码的灵活性。
4. 统一接口:通过继承,可以定义一个抽象的父类,然后定义多个子类来实现具体的功能。
这样可以实现统一的接口,使代码更加规范和易于管理。
5. 多态性的实现:继承是实现多态性的基础。
子类可以替代父类的位置,通过父类的引用来调用子类的方法。
这样可以实现动态绑定,提高了代码的灵活性和可扩展性。
二、派生的作用1. 创建新的类:派生是在继承的基础上创建新的类的过程。
通过派生,可以基于已有的类创建新的类,并在新的类中添加、修改或重新实现属性和方法。
2. 特化和泛化:通过派生,可以根据具体的需求创建特定的类。
例如,可以从一个通用的动物类派生出狗类和猫类,使它们具有更具体的属性和方法。
同时,也可以从一个具体的类派生出一个更通用的类,使它具有更广泛的适用性。
3. 继承关系的传递:通过派生,可以传递继承关系。
即子类可以继续被其他类所派生,形成更深层次的继承关系。
这样可以实现更复杂的类之间的继承和关联。
4. 重载和重写:通过派生,可以重载和重写父类的方法。
重载是指在子类中定义一个与父类同名但参数列表不同的方法,以实现不同的功能。
重写是指在子类中重新定义一个与父类同名同参数列表的方法,以实现不同的行为。
《继承与派生 》课件
目录
CONTENTS
• 继承与派生的基本概念 • 继承的方式 • 派生类的构造函数和析构函数 • 继承与多态 • 继承与重载
01
继承与派生的基本 概念
继承的定义
继承是面向对象编程中的一个重 要概念,它允许一个类(子类) 继承另一个类(父类)的属性和
方法。
通过继承,子类可以复用父类的 代码,减少代码冗余,提高代码
保护继承
总结词
保护继承是指基类的保护成员在派生类 中保持保护属性,可以被派生类和派生 类的对象访问。
VS
详细描述
保护继承时,基类的保护成员在派生类中 保持保护属性,可以被派生类和派生类的 对象访问。这种继承方式使得基类的保护 成员成为派生类的保护成员,可以被派生 类和派生类的对象访问。因此,派生类可 以继承基类的保护成员函数和变量。
03
派生类的构造函数 和析构函数
派生类的构造函数
派生类构造函数的作用
派生类构造函数用于初始化派生类对象,包括调用基类构造函数 和执行派生类特有的初始化操作。
派生类构造函数的执行顺序
派生类构造函数的执行顺序是在创建派生类对象时,先调用基类构 造函数,然后执行派生类构造函数体中的代码。
派生类构造函数的参数
继承和派生共同实现 了面向对象编程中的 代码复用和多态性。
派生是继承的一种表 现形式,通过派生可 以创建新的类。
02
继承的方式
公有继承
总结词
公有继承是ቤተ መጻሕፍቲ ባይዱ基类的公有成员在派生类中仍为公有成员,可以被派生类和派生类的对象访问。
详细描述
公有继承时,基类的公有成员在派生类中保持公有属性,派生类可以访问基类的公有和保护成员。这种继承方式 使得基类的公有成员成为派生类的公有成员,可以被派生类和派生类的对象直接访问,因此派生类可以继承基类 的公有成员函数和变量。
第7章 继承和派生
例:7.3分析下列程序的结果:
class Base1 { public: Base1(int i ) { b1=i ; cout<<"Constructor of Base1."<<endl; }
void Print() const
private:
{ cout<<b1<<endl; }
int b1;
Member ( int i)
{ m=i ; cout<<"Constructor of Member."<<endl; } int GetM ( ) { return m; } private: int m; };
16
class Derived : public Base2, public Base1 ,public Base3
{ b1=i;
b2=j;
cout<<"Base's constructor called."<<b1<<","<<b2<<","<<endl;
} Base::~Base ( ) {cout<<"Base's }
destructor called."<<b1<<","<<b2<<","<<endl;
23
Base's destructor called.1,2,
27
§7.4多继承与虚基类
§7.4.1多继承中的二义性问题 产生二义性问题主要有两种情况: ㈠产生二义性问题的第一种情况如下例: 如P215图7.4(a) class Base1 { public: void fun(); };
第七章 继承选择题
1、下列对基类和派生类关系的描述中,错误的是_________。
A)派生类是基类的具体化B)派生类是基类的子集C)派生类是基类定义的延续D)派生类是基类的组合2、继承具有_________ ,即当基类本身也是某一个类的派生类时,底层的派生类也会自动继承间接基类的成员。
A)规律性B)传递性C)重复性D)多样性3、下面_________的叙述不符合赋值兼容规则。
A)派生类的对象可以赋值给基类的对象B)基类的对象可以赋值给派生类的对象C)派生类的对象可以初始化基类的引用D)派生类的对象的地址可以赋值给指向基类的指针5、下面叙述错误的是_________。
A)派生类可以使用private派生B)对基类成员的访问必须是无二义性的C)基类成员的访问能力在派生类中维持不变D)赋值兼容规则也适用于多继承的组合6、下列说法中错误的是_________。
A)公有继承时基类中的public成员在派生类中仍是public的B)公有继承时基类中的private成员在派生类中仍是private的C)私有继承时基类中的public成员在派生类中是private的D)保护继承时基类中的public成员在派生类中是protected的7、C++的类有两种用法:一种是类的实例化,即生成类的对象,并参与系统的运行;另一种是通过_________派生出新的类。
A)复用B)继承C)封装D)引用8、下列关于虚基类的描述中,错误的是_________。
A)虚基类子对象的初始化由最派生类完成B)虚基类子对象的初始化次数与虚基类下面的派生类个数有关C)设置虚基类的目的是消除二义性D)带有虚基类的多层派生类构造函数的成员初始化列表中都要列出对虚基类构造函数的调用9、派生类的构造函数的成员初始化列表中,不能包含_________。
A)基类的构造函数B)派生类中子对象的初始化C)基类中子对象的初始化D)派生类中一般数据成员的初始化10、C++类体系中,不能被派生类继承的有_________。
继承与派生类答案
继承与派生类知识要点1.掌握继承和派生的定义,派生类的定义方法。
(1)掌握继承的两种类型:单继承和多继承。
(2)掌握private,public,protected三种继承方式的特点。
继承方式决定了基类中的成员在派生类中的属性。
三种继承方式的共同点:基类的private成员在派生类中不可见。
区别:对于私有继承,基类的public、protected成员在派生类中作为private成员;对于公有继承,基类的public、protected成员在派生类中访问属性不变;对于保护继承,基类的public、protected成员在派生类中作为protected成员。
(3)掌握派生类中的构造函数和析构函数的使用。
基类的构造函数和析构函数不能继承,所以必要时在派生类中定义自己的构造函数和析构函数。
派生列的构造函数完成基类中新增数据成员和基类数据成员的初始化,基类数据成员的初始化通过基类构造函数来实现。
(4)掌握派生类的同名覆盖规则。
(5)掌握赋值兼容规则。
基类对象可以使用公有派生类对象来代替,包括:派生类对象可以赋值给基类对象;派生类对象可以初始化基类对象的引用;基类类型指针可以指向派生类对象。
2.掌握多重继承的概念、定义方法、多重继承派生类构造函数的执行顺序。
派生类构造函数的执行顺序是先执行所有基类的构造函数(顺序按照定义派生类时指定的各基类顺序),在执行对象成员所在类的构造函数(顺序按照他们在类中的声明顺序),最后执行派生类构造函数体中的内容。
3.掌握虚基类的概念和定义方法。
在多重继承中,如果多条继承路径上有一个公共的基类,则在这些路径的汇合点上的派生类会产生来自不同路径的公共基类的多个拷贝,如果用virtual把公共基类定义成虚基类,则只会保留公共基类的一个拷贝。
典型例题分析与解答例题1:下列对派生类的描述中,()是错误的。
A.一个派生类可以作为另一个派生类的基类B.派生类至少有一个基类C.派生类的成员除了它自己的成员外,还包含了它的基类成员D.派生类中继承的基类成员的访问权限到派生类保持不变答案:D分析:一个派生类可以作为另一个派生类的基类。
《继承和派生》课件
派生类的析构函数
派生类析构函数在销毁派生类对象时 自动调用,用于释放派生类所占用的 资源。
派生类析构函数可以包含代码,用于 清理派生类所占用的资源。
派生类析构函数可以访问基类的析构 函数,通过使用`this`关键字调用基类 析构函数。
派生类析构函数可以重载基类析构函 数,以便在销毁派生类对象时执行特 定的操作。
基类析构函数的调用
在派生类的析构函数中,可以通过使用`this`关键字调 用基类的析构函数,以确保基类资源得到正确释放。
输标02入题
如果在派生类的析构函数中没有显式调用基类的析构 函数,则编译器会自动调用基类的默认析构函数。
01
03
在某些情况下,可能需要显式调用基类的析构函数, 以确保资源得到正确释放。例如,当基类包含动态分
02 继承的方式
公有继承
总结词
公有继承是指子类可以访问父类的公有成员。
详细描述
在公有继承中,子类可以访问父类的公有成员(即不加任 何修饰符的成员),这些成员在子类中保持公有属性。子 类可以继承和使用父类的公有成员,包括函数、变量、常 量等。
总结词
公有继承是实现代码复用的一种方式。
详细描述
通过公有继承,子类可以继承父类的公有成员,从而避免 重复编写相同的代码。这有助于提高代码的复用性和维护 性。
注意事项
虚函数和纯虚函数的使用 应合理规划,避免过度使 用导致程序复杂度和维护 成本增加。
继承和派生的效率问题
继承
通过共享已存在的代码, 减少代码冗余。但也可能 导致内存浪费和性能下降 。
派生
通过扩展已有类,增加新 功能或修改已有功能。但 也可能导致内存消耗增加 和性能下降。
注意事项
派生与继承
继承与派生
(2)改造。改造是指对吸收进来的基类成员的改 改造。 改造 造。它包括两个方面:一个是对基类成员访问 它包括两个方面: 控制的调整, 控制的调整,它是通过派生类定义时的继承方 式来确定。另一个就是对基类成员的隐藏, 式来确定。另一个就是对基类成员的隐藏,即 在派生类中声明一个与基类成员同名的新成员, 在派生类中声明一个与基类成员同名的新成员, 这个新成员就隐藏了上层的所有同名成员。 这个新成员就隐藏了上层的所有同名成员。这 时,在派生类中或者通过派生类的对象来直接 使用该成员名, 使用该成员名,就只能访问到派生类中声明的 同名成员,这称为同名隐藏或同名覆盖。 同名成员,这称为同名隐藏或同名覆盖。
继承与派生
继承性的具体实现也就是一个派生类的建立过程。 继承性的具体实现也就是一个派生类的建立过程。 class 派生类名 : 继承方式 基类名 继承方式 基类名 基类名1, 基类名2, … , 继承方式 基类名 基类名n { 新增派生类成员声明; 新增派生类成员声明 }; 继承方式关键字有三个: 继承方式关键字有三个:public、private、protected。 、 、 。 继承方式关键字只对紧随其后的基类起作用。 继承方式关键字只对紧随其后的基类起作用。 在继承与派生的过程中,一个基类可以派生出多个派生类, 在继承与派生的过程中,一个基类可以派生出多个派生类, 每一个派生类又可以作为基类再派生出新的派生类, 每一个派生类又可以作为基类再派生出新的派生类,基类和 派生类是相对而言的。这样,一代一代地派生下去, 派生类是相对而言的。这样,一代一代地派生下去,就形成 了一个相互关联的有层次的类的家族,称为类族。在类族中, 了一个相互关联的有层次的类的家族,称为类族。在类族中, 作为上下层直接联系而参与派生出某类的基类称为该派生类 的直接基类, 的直接基类,而基类的基类甚至更高层的基类则称为间接基 类。
继承和派生——类与类之间的关系、继承的基本概念、继承的方式、继承中的构造和析构
继承和派⽣——类与类之间的关系、继承的基本概念、继承的⽅式、继承中的构造和析构1、类与类之间的关系 has-A,uses-A 和 is-A has-A 包含关系,⽤以描述⼀个类由多个“部件类”构成。
实现has-A关系⽤类成员表⽰,即⼀个类中的数据成员是另⼀种已经定义的类。
uses-A ⼀个类部分地使⽤另⼀个类。
通过类之间成员函数的相互联系,定义友员或对象参数传递实现。
is-A 机制称为“继承”。
关系具有传递性,不具有对称性。
class A{public:void funcA(){}int a;};//类B拥有类A的成员变量,B has A,类B 依赖于类Aclass B{public:void funcB(){}A a;};//类C的成员⽅法需要类A的形参,C use A,类C 依赖于类Aclass C{public:void funcC(A *a){}void funcCC(){}};//类D继承于类A, 类D如果是继承类A,类D is 类A,类C 继承于类A,耦合度很⾼class D:public A{public:void funcD(){cout << a << endl;}};2、继承的基本概念 类的继承,是新的类从已有类那⾥得到已有的特性,或从已有类产⽣新类的过程就是类的派⽣。
原有的类称为基类或⽗类,产⽣的新类称为派⽣类或⼦类。
派⽣与继承,是同⼀种意义两种称谓。
is-A 的关系。
派⽣类的⽣成 派⽣类中的成员,包含两⼤部分,⼀类是从基类继承过来的,⼀类是⾃⼰增加的成员。
从基类继承过过来的表现其共性,⽽新增的成员体现了其个性。
⼏点说明:1,全盘接收,除了构造器与析构器。
基类有可能会造成派⽣类的成员冗余,所以说基类是需设计的。
2,派⽣类有了⾃⼰的个性,使派⽣类有了意义。
只能在当前类中访问的成员设置为private3、只能在当前类和⼦类中访问的成员设置为protected,protected成员的访问权限介于public和private之间。
C类的继承和派生ppt课件
cout<<"("<<x<<","<<y<<")"<<en dl; }
-
//Circle.h文件 #ifndef CIRCLE_H #define CIRCLE_H #include <iostream> #include "Point.h" using namespace std; class Circle:public Point { protected:
name=nam; sex=s; } ~Student( ){ } protected: int num; string name; char sex ; };
-
class Student1: public Student { public:
Student1(int n,string nam,char s,int a,string ad):Student(n,nam,s)
using namespace
std;
{ protected:
class Base
int j;
{ protected:
int i; public:
void F()
public: void Fun() { i=20; }
};
{
void main()
} };
{ Drived d;
}
-
4.5 派生类的构造函数和析构函数
如程序PointRect1所示:
-
4.4继承方式
C语言程序设计第七章继承性和派生类.
};
第七章
五、基类与派生类的关系:
1、派生类是基类的具体化: 基类是对若干个派生类的抽象,而派生类是基类 的具体化。基类抽取了它的派生类的公共特征,而派 生类通过增加行为将抽象类变为某种有用的类型。
输入设备
键盘
鼠标器
数字化仪
第七章
2、派生类是基类定义的延续: 先定义一个抽象基类,该基类中有些操作并未实 现。然后定义非抽象的派生类,实现抽象基类中定义的 操作。这时,派生类是抽象的基类的实现,即可看成是 基类定义的延续。这也是派生类的一种常用的方法。 3、派生类是基类的组合: 在多继承时,一个派生类有多于一个的基类,这时派 生类将是所有基类行为组合。
第七章 A's destructor called. B's destructor called. A's destructor called. A's destructor called
第五节
子类型和赋值兼容规则
第七章
一、子类型:
有一种类型A,它至少包含有另一种类型B的所有 行为,则称类型A是类型B的子类型。子类型的关系是 不可逆的。
第七章 } void main() { B bb[2]; bb[0]=B(1,2,5); bb[1]=B(3,4,7); for(int i=0;i<2;<i++) bb[i].Print(); }
第七章答案继承、虚基类
7.3 练习题解答1.什么是继承性?为什么说它是面向对象程序中的重要机制?答:继承是指一个对象是另一个对象的特例,则称这个对象继承了另一个对象。
继承是创建新类的一种手段,通过继承生成的新类中包含了被继承类中的所有成员,并且它还具有自己定义的成员。
继承性是面向对象程序设计方法中两大标志之一,即封装性和继承性。
继承性将提高可重用性,这是面向对象程序设计的重要特性。
继承性又是多态性的重要基础。
2.C十十中继承分为哪两类?继承方式又分哪3种?答:C十十语言支持两种继承:单继承和多继承。
有的面向对象程序设计语言只支持单继承,例如Java语言。
C十十语言中继承方式分为3种:公有继承(Public)、私有继承(private)和保护继承(protected)。
3.3种继承方式中各有什么特点?不同继承方式中派生类对基类成员的访问有何不同?答:继承方式有3种,它们区别在于不同继承方式使得基类成员在派生类中的访问权限不问。
具体讲来,公有继承方式时,基类中的公有和保护成员在派生类中仍是公有和保护成员;私有继承方式时,基类中的公有成员和保护成员在派生类中都为私有成员;保护继承方式时,基类中的公有成员和保护成员在派生类中都是保护成员。
3种方式中,基B类为A类的子类型,就称它们类型适应。
这时,B类对象就是A类对象。
可将B类对象直接赋值给A类对象。
反之不行。
另外,还可用B类对象初始化A类对象的引用,用B类对象的地址值赋给指向A类对象的指针。
9.多继承中,在哪些情况下会出现二义性?如何消除二义性?答:多继承中在下列两种情况下可能出现二义性:(1)访问不同基类中的相同成员可能出现二义性。
(2)访问共同基类中的成员时可能出现二义性。
·消除二义性的方法是适当地选择成员名限定的方法,这时要使用作用域运算符::。
10.为什么要引入虚基类?带有虚基类的派生类的构造函数有什么特点?答:引入虚基类的目的是为了解公共基类可能造成的二义性。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
{
派生类新定义成员
};
public表示公有继承
继承方式private表示私有继承
protected表示保护继承
继承方式规定了如何访问从基类继承的成员。继承方式缺省,隐含私有继承。
多继承的定义格式如下:
class派生类名:继承方式1基类名1,
继承方式2基类名2,…
{
派生类新定义成员
例7.9
#include<iostream.h>
class A
{public:
A( ){a=0;}
A(int i){a=i;}
void Print( ) {cout<<a<<”,”;}
private:
int a;
};
class B:public A
{public:
B( ){b1=b2=0; } //隐式调用A的构造函数
解决的方法:
(1)成员名限定法来消除二义性,例如:
c1.A::f( );或者c1.B::f( );
7.2单继承
7.2.1成员访问权限的控制
例7.2
#include<iostream.h>
class A
{public:
void f(int i){cout<<i<<endl;}
void g( ){cout<<”g\n”;}
};
class B:A
{public:
void h( ){cout<<”h\n”;}
7.2.2派生类的构造和析构函数
派生类继承了基类的成员,实现了原有代码的重用,这只是一部分,而代码的扩充才是最主要的,只有通过添加新的成员,加入新的功能,类的派生才有实际意义。基类的构造函数和析构函数不能被继承。在派生类中,如果对派生类新增的成员进行初始化,就必须由程序员针对实际需要加入新的构造函数。与此同时,对所有从基类继承下来的成员的初始化工作,还是由基类的构造函数完成,我们必须在派生类中对基类的构造函数所需要的参数进行设置。
A::f;
};
void main( )
{B d1;
d1.f(6);
d1.g( );
d1.h( );
}
问题:
1.d1.g( );出现编译错。
2.去掉d1.g( );执行结果为:
6
h
3. A::f;将基类中的公有成员说明成派生类的公有成员。
4.将私有继承改为公有继承输出为:
6
g
h
例7.3
#include<iostream.h>
{public://新增公有成员Rectangle(float x,float y,float w,float h )
:Point(x,y)
{W=w;H=h;}
void 2( )
{cout<<W<<”,”<<H<<endl;}
private://新增私有数据成员
float W,H;
};
void main( )
在这个层次结构中,由上到下,是一个具体化、特殊化的过程;由下到上,是一个抽象化的过程。最高层抽象程度最高,从上到下加入了自己的新特征,而最下层是最为具体的。
在派生过程中,派生出来的新类也同样可以作为基类再继续派生新的类。直接参与派生出某类的基类称为直接基类。基类的基类称为间接基类,比如A类派生出B类,B类又派生出C类。则B类是C类的直接基类,A类是B类的直接基类。而A类可以称为C类的间接基类。
constructor B1.1
constructor B3.3
constructor A.4
1
2
4,3
说明:
1.派生类A的构造函数。
A(int i,int j,int k,int l):B1(i),B2(j),bb(k)
{a=l;
cout<<"constructor A."<<l<<endl;}
2.派生类构造函数的执行顺序。
取决于定义派生类时所指定的各基类顺序,与派生类构造函数中所定义的成员初始化列表的各项顺序无关。
3.作用域运算符::的作用。
B1::print( );
B2::print( );
7.3.3二义性问题
第一种情形:
一般说来,在派生类中对基类成员的访问应该是唯一的,但是,由于多继承情况下,可能造成对基类中某成员的访问出现了不唯一的情况,则称为对基类成员访问的二义性问题。下面举一个简单的例子,对二义性问题进行深入讨论
{B d1;
B d2(5);
B d3(4,5,6);
d1.print( );
d2.print( );
d3.print( );
}
输出:
0,0,0
0,5,0
4,5,6
7.3多继承
7.3.1多继承的概念
多继承是指派生类具有多个基类。
多继承的定义格式如下:
class派生类名:继承方式1基类名1,
继承方式2基类名2,…
1.构造函数
派生类构造函数的一般形式为:
派生类名(派生类构造函数总叁数表)
:基类构造函数(参数表1),子对象名(参数表2)
{派生类中数据成员初始化}
派生类构造函数执行的一般次序如下:
1.基类构造函数。
2.子对象的构造函数。
3.派生类构造函数
例7.4公有继承
#include<iostream.h>
class Point//基类Point
5,5
20,10
2.析构函数
当对象被删除时,派生类的析构函数被调用。由于基类的析构函数也不能继承,因此在执行派生类的析构函数时,基类的析构函数也被调用。执行的顺序是先执行派生类的析构函数,再执行基类的析构函数。
3.派生类构造函数使用中注意的问题
派生类构造函数的定义中可以省略对基类构造函数的调用,其条件是在基类中必须有缺省构造函数或者根本没有定义构造函数。
新定义成员成员
派生类的对象可以访问基类中的公有成员;派生类的成员函数可以访问基类中的公有成员和保护成员。
2.私有继承(private)
私有成员只能在类中可见,不能再类外或派生类中使用。
特点:基类中的公有成员和保护成员都以私有成员身份出现在派生类中,而基类的私有成员在派生类中不可访问。
private成员
{public:
B2(int i)
{b2=i;cout<<"constructor B2."<<i<<endl;}
void print( ) { cout<<b2<<endl;}
private:
int b2;
};
class B3//基类B3
{public:
B3(int i)
{b3=i;cout<<"constructor B3."<<i<<endl;}
private成员
Protected成员protected成员
public成员protected成员
private成员
protected成员
public成员
基类成员
派生类
新定义成员成员
派生类的成员函数可以访问基类中的公有成员和保护成员。
三种不同的继承方式的基类和派生类特性。
7.1.3基类与派生类的关系
int getb3( ) {return b3;}
private:
int b3;
};
class A: public B2, public B1//派生类A{ public:
A(int i,int j,int k,int l):B1(i),B2(j),bb(k)
{a=l;
cout<<"constructor A."<<l<<endl;}
{public:
Point(float xx=0,float yy=0){X=xx;Y=yy;}
void Move(float x,float y) {X+=x;Y+=y;}
void print1( )
{cout<<X<<”,”<<Y<<endl;}
private:
float X,Y;
};
class Rectangle: public Point//派生类
7.1基类和派生类
我们称已存在的用来派生新类的类为基类,又称为父类。由已存在的类派生出的新类称为派生类,又称为子类。
在C++语言中,一个派生类可以从一个基类派生,也可以从多个基类派生。从一个基类派生的继承称为单继承;从多个基类派生的继承称为多继承。
单继承多继承
7.1.1派生类的定义格式
单继承的定义格式:
void print( )
{B1::print( );
B2::print( );
cout<<a<<”,”<<bb.getb3( )<<endl;}
private:
int a;
B3 bb;
};
void main( )
{A aa(1,2,3,4);
aa.print( );
}
输出:
constructor B2.2
};
7.1.2派生类的三种继承方式
1.公有继承(public)
公有成员是类的接口,在类中和类外可见。
特点:基类的公有和保护成员的访问属性在派生类中不变、而基类的私有成员不可访问。