继承与多态的关系?
发布网友
发布时间:2022-03-27 12:47
我来回答
共4个回答
热心网友
时间:2022-03-27 14:17
继承貌似和多态关系不大??
一、类的继承
类是一种抽象数据类型,是对具有共同属性和行为的对象(事物)的抽象描述。但通常为了处理问题的方便,对事物按层进行分解,使得处于顶层(上层)的抽象事物具有处于底层(下层)抽象事物的共同特征,而处于底层的抽象事物除了具有顶层抽象事物的所有特征外,还具有本身所专有的特征。例如对于建筑物来说,它有施工单位、竣工日期等特征;而建筑物又可细分为房屋、桥梁和纪念塔等三类,它们除了具有建筑物的共同特征外,还各自具有自己的特征,如房屋有建筑面积,桥梁有建筑高度、宽度和长度,纪念塔有塔高和形状等特征;房屋又可细分为平房和楼房两类,平房和楼房除了具有房屋的共同特征外,还具有自己的特征,如平房有庭院面积,楼房有楼层数和电梯数等特征;楼房又可细分为办公楼和居民楼两类,它们除了具有楼房的公共特征外,办公楼还具有值班电话,居民楼还具有居民户数和居住人数等特征。可用图9-1表示它们之间的层次关系。
建筑物
房屋 桥梁 纪念塔
平房 楼房
办公楼 居民楼
图1 建筑物类层次图
在C++中允许定义类之间的继承关系。当一个类继承另一个类时,这个类被称为继承类、派生类或子类,另一个类被称为被继承类、基类或父类。子类能够继承父类的全部特征,包括所有的数据成员和成员函数,并且子类还能够定义父类所没有的、属于自己的特征,即自己的数据成员和成员函数。通过类的继承关系,使得一些类的代码可以为定义另一些类所重用,避免了代码的重新书写和调试,能够开发出便于维护和扩充、可靠性高的软件。所以,类的继承是软件开发中的一项重要技术。
1. 派生类定义的格式
class <派生类名> : <基类表> {<成员表>};
它同一般类的定义格式大体相同,只是在类名和左花括号之间增添了一个冒号和一个基类表。
语句定义中的派生类名是新定义的类类型标识符,它是基类表中所给基类的一个派生类;基类表中包含有一个或多个用逗号分开的类项,每个类项为一个已被定义的作为基类使用的类名,它前面可以带有继承权限指明符用以规定被继承的权限;花括号内的成员表是为该派生类定义的数据成员和成员函数的列表。
基类表中每个基类名前面可以使用的继承权限指明符仍为类成员表中为规定成员访问权限所使用的指明符public,private或protected,它们分别表示派生类公用(公有)、私有或保护继承该基类。若一个基类名前没有使用任一指明符也是允许的,对于class定义语句来说,隐含为private指明符,即派生类私有继承该基类,对于struct定义语句来说,隐含为public指明符,即派生类公用继承该基类,这种规定与定义它们的成员时缺省的访问权限的规定完全相同。
当一个基类被派生类公用继承时,则基类中的所有public成员也同时成为派生类中的public成员,基类中的所有protected成员也同时成为派生类中的protected成员,基类中的所有private成员不转换为派生类中的任何成员,仍作为基类的私有成员保留在基类中,也可以说同时保留在派生类中,因为派生类继承了基类中的所有成员。由于基类的私有成员没有同时成为派生类中的成员,所以派生类的成员函数无法直接访问它们,只能通过基类提供的公用或保护成员函数来间接访问。当然,若把派生类定义为基类的友元,则可直接访问其私有成员。
当一个基类被派生类私有继承时,则基类中的所有public成员和所有protected成员将同时成为派生类中的private成员,基类中的所有private成员仍只作为基类的私有成员存在,不转换为派生类中的任何成员。
当一个基类被派生类保护继承时,则基类中的所有public成员和所有protected成员将同时成为派生类中的protected成员,基类中的所有private成员同上述两种继承一样,仍只能作为基类的私有成员存在,不是派生类的成员。
无论任何一个类,无论它的成员是靠继承而来的,还是自己定义的,都属于自己的成员,该类的成员函数能够访问该类中具有任何访问权限的成员,同时也能够访问其他类中具有公用访问权限的成员和类外的对象与函数,不能访问其他类中的保护成员和私有成员,即使其他类是自己继承的类,或自己成员所属的类也是如此。
在一个派生类中,其成员由两部分组成,一部分是从基类继承得到的,另一部分是自己定义的新成员,所有这些成员也分为公用(public)、私有(private)和保护(protected)这三种访问属性。另外,从基类继承下来的全部成员构成派生类的基类部分,此部分的私有成员是派生类不能直接访问的,其公用和保护成员是派生类可以直接访问的,因为它们已同时成为了派生类中的成员,但在派生类中的访问属性可能有改变,视对基类的继承权限而定。带有一个基类的派生类的构成如图2所示。
私有成员
基类部分 保护成员
派生类 公共成员
私有成员 派生类成员
新定义部分 保护成员
公用成员
图2 派生类构成示意图
当派生类公用继承基类时,派生类中的公用成员包括基类部分的公用成员和新定义部分的公用成员,保护成员包括基类部分的保护成员和新定义部分的保护成员,私有成员仅为新定义部分的私有成员。当派生类保护继承基类时,派生类中的公用成员仅为新定义部分的公用成员,保护成员包括基类部分的公用成员和保护成员以及新定义部分的保护成员,私有成员仅为新定义部分的私有成员。当派生类私有继承基类时,派生类中的公用成员仅为新定义部分的公用成员,保护成员也仅为新定义部分的保护成员,私有成员包括基类部分的公用成员和保护成员以及新定义部分的私有成员。
每个派生类对象所占有的存储空间的 大小等于其基类部分的所有数据成员占有的存储空间的大小与新定义部分的所有数据成员占有的存储空间大小的总和,并且前面的存储空间分配给基类部分的数据成员使用,后面的存储空间分配给新定义部分的数据成员使用。
2. 格式举例
(1) struct X {
int a;
};
struct Y: X {
int b;
int c;
};
这里X和Y均为结构,所以它们的成员缺省为公用访问属性,Y对X的继承也缺省为公用继承。派生类Y中包含有三个公用成员a,b和c,其中a又同时为基类X部分的公用成员。由于Y中的成员都是公用的,所以外部函数可以直接访问以Y为类型的对象中的任何成员。每个Y类型的对象具有12个字节的存储空间,其中前4个字节存储数据成员a,接着4个字节存储数据成员b,最后4个字节存储数据成员c。假定y是Y结构类型的一个对象,则y.a,y.b和y.c都是有效的表示,利用它们可以访问y中的指定成员。当然y.a也可以表示为y.X::a,因为a同时又是y结构中的基结构类型X中的成员。
(2) class A {
int a1;
protected:
int a2;
public:
int a3;
A() {a1=a2=a3=0;}
A(int x1, int x2, int x3):a1(x1),a2(x2),a3(x3) {}
void OutA() {cout<<a1<<' '<<a2<<' '<<a3<<endl;}
int Geta1() {return a1;}
};
class B: public A {
int b1;
protected:
int b2;
public:
int b3;
B() {b1=b2=b3=0;}
B(int x1, int x2, int x3): A(x1,x2,x3) {
b1=x1+1; b2=x2+2; b3=x3+3;
}
void OutB() {
A::OutA();
cout<<b1<<' '<<b2<<' '<<b3<<endl;
}
int Sum() {
return Geta1()*b1+a2*b2+a3*b3;
}
};
void main()
{
B b1,b2(1,2,3);
b1.OutB();
b2.OutB();
cout<<b1.Sum()<<' '<<b2.Sum()<<endl;
cout<<sizeof(B)<<endl;
};
热心网友
时间:2022-03-27 15:35
继承有实现集成,还有接口继承.
前者:派生类可以使用基类的实现.
后者:为面向对象(多态)编程做准备.
所以多态是面向对象编程的基础,通过向一个含基类指针参数的函数传递某个它的派生类指针,函数体里调用虚函数达到多态效果.
这样就可以根据变化,扩展出新的派生类,那么就可以直接拿来使用(接口不变的前提下),就不用大规模更改程序代码了.
多看些代码吧,说多了没用.
拜拜.
热心网友
时间:2022-03-27 17:09
够详细...
热心网友
时间:2022-03-27 19:01
靠。回答那么多做什么