帮助手册1c程序设计语言教程第18章_第1页
帮助手册1c程序设计语言教程第18章_第2页
帮助手册1c程序设计语言教程第18章_第3页
帮助手册1c程序设计语言教程第18章_第4页
帮助手册1c程序设计语言教程第18章_第5页
已阅读5页,还剩19页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1

四、派生类的三种继承方式

五、继承和不继承的语义

六、派生与继承的算例

七、构造和析构的次序第18章组合和继承2四、派生类的三种继承方式

关键字[private,public,protected]具有双重含义:

1.明确界定同一类层次中各成员的访问控制属性;2.是指类上下关系中派生类对于基类成员的访问控制属性的隐含演化规则。派生类的继承方式就是指第二个含义而言。首先抓住下面几个主要的概念:

a.

继承不影响基类的数据成员分配,不破坏基类的独立性;

b.

所有的数据成员都占有内存,静态数据成员被唯一地放置在全局数据区。3

c.

派生类对象占有的内存是基类对象占有的内存和派生类新增数据成员的内存之和。

d.

类层次本身的访问控制属性和继承方式对于对象的内存分配无影响。通过继承无论是私有继承还是公共继承,派生类的对象既潜在地继承上层基类的所有数据状态也潜在地拥有基类所有的成员函数。派生类对于基类的成员访问控制属性受制于两个因素,基类本身成员的访问控制属性,派生类相对于基类的继承方式控制。4下面是关于编译器继承方式的描述:

1).

对于任意继承方式,基类的私有成员对于派生类是“不可访问的”。

2).

对于公共继承方式,基类的公共成员为派生类的公共成员,基类的保护成员为派生类的保护成员。

3).

对于保护继承方式,基类的公共的和保护的成员变为派生类的保护成员。

4).

对于私有继承方式,基类的公共的和保护的成员变为派生类的私有成员。5

除开禁止派生类访问的基类的私有成员以外,无论是继承的成员还是新增的成员,派生类的成员访问控制属性只有三种:1).

可以在任何位置访问的公共成员。

2).

可以出现在派生类中的保护成员。

3).

不出现在派生类的私有成员。保护成员和私有成员仅由类的成员函数或者友元函数访问,禁止派生类对象外部访问。公共成员允许对象外部访问。访问控制对于类作用域所有的名称是同等适用的。这些名称包括成员名、类中的枚举常数名称和嵌套类。6五、继承和不继承的语义

C++语言在关于继承的特殊函数时指出:不参与继承的特殊函数是构造函数、析构函数、赋值运算符函数和作为特权地位的友元函数。前已指出派生类继承了基类的数据状态。 即便是私有继承,基类的私有成员依然成为派生类对象内存的一部分。友元函数不继承的含义是指:友元函数形参列表的基类的对象指针只能够无禁锢的访问基类的所有成员,这种特权地位不因派生类的继承关系而使得基类的特权函数也获得对派生类成员的无条件访问。7

继承的含义:基类的数据成员和函数成员在派生类可访问的环境下可当作派生类的一个有机组成部分,就好像上下层次的区分并不存在一样。

继承的含义指形如obj.m_n或pobj->f()访问格式,如果派生类中存在相应的成员直接采用派生类的成员。如果派生类没有提供相关的成员,则使用从基类继承的可访问成员。派生类成员函数的定义遵循基类的一般规则,但派生类继承了基类的数据成员和成员函数。根据继承的方式和继承的语义操作相应的信息。8

构造函数和析构函数不能继承表现一种对象分而制之的思想,基类负责构造自身的数据成员,派生类负责构造继承的和新添补的数据成员,这样有利于派生类缺省构造函数自动调用基类的缺省构造函数。相应的析构函数执行各自的清理工作。 这种对象处理当前类数据的思想并非不适应于其它可以继承的成员函数,但由于构造和析构函数被系统自动调用的特殊性,上下类层次之间的操作有必要加以严格的界定。9

基类的构造函数恰恰是可以被派生类构造函数以基类名显式调用的函数,不能继承的特殊函数实际上是要求重点处理的函数,对于不继承的函数应该精心提交派生类的相应版本,以分别处理数据的变动情况。在这里不继承的含意是指派生类的对象自动调用的是自身类的构造函数,而不隐含地向上借用。赋值运算符函数的作用类似拷贝构造函数,不参入继承机制。特别地如果类中存在指针成员,程序员应仔细处理指针的动态内存资源。如果用户未提交构造函数和析构函数或赋值运算符函数,编译器生成相应的简单版本满足最低化的要求。10

继承的含义是指基类的数据成员和函数成员在派生类可访问的环境下可当作派生类的一个有机组成部分,就好像上下层次的区分并不存在一样。 继承的含义指形如obj.m_n或pobj->f()访问格式,如果派生类中存在相应的成员直接采用派生类的成员。如果派生类没有提供相关的成员,则使用从基类继承的可访问成员。派生类成员函数的定义遵循基类的一般规则,但派生类继承了基类的数据成员和成员函数。根据继承的方式和继承的语义操作相应的信息。11六、派生与继承的算例[例]B类公共地继承A类,A类的公共成员是B类的公共成员#include<stdio.h>classA{public:long&X(){returnx;} protected:longx; };classB:publicA{public:B(){x=1;}};classC:publicB{/*public:B::x;*/};voidmain(){Cb;long*p=&(b.X()+=1);printf("%d\n",*p);} //输出:212[例]B类保护地继承A类,A类保护的或公共的成员是B类的保护成员#include<stdio.h>classA{protected:longx;};classB:protectedA{public:long&X(){returnx;}};classC:protectedB{public:B::X;};//C类保护地继承B类voidmain()

//public:B::X;界定成员的控制属性优于

//继承方式protected的控制属性{Cb;

//public:B::X;表示将基类中保护的成员在

//派生类中界定为public属性

long*p=&(b.X()=1);printf("%d\n",*p);}//输出:113[例]B类私有地继承A类,A类的公共的或保护的成员是B类的私有成员#include<stdio.h>classA{private:longx; public:long&X(){returnx;}};classB:A{public:longy;long&Y(){returnX();}};classC:privateB{public:B::Y;};voidmain()//public:B::Y;将基类中公

//共的成员在派生类中界定为public属性{ Cc;long*p=&(c.Y()=1);printf("%d\n",*p);} //输出:114[例]B类保护地继承A类,C类私有地继承B类。#include<stdio.h>classA {protected:longx;};classB:protectedA{public:long&operator+=(intn){returnx+=n;}};classC:privateB{public:B::operator+=;public:B::x;};voidmain(){Cb;b.x=1;long*p=&(b+=2);printf("%d,%d\n",*p,b.x);}//输出:3,315七、构造和析构的次序生成派生类的对象时编译器按照如下的次序调用构造函数:

1.

基类构造函数。多继承情形先声明的先调用即从左到右的次序调用基类构造函数。

2.

同一类层次中嵌入对象的构造函数,嵌入对象构造函数按照在类中的声明次序依次调用,与成员初始化语法的排放次序无关。嵌入对象如果存在才调用。

3.

派生类的构造函数。确保继承树层次的构造函数全被调用一次。

16

4.

总的原则是从左到右从上到下由内向外调用构造函数。下面是构造函数成员初始化在单继承含一个嵌入对象时的语法格式:

CDerived::CDerived(t1v1,t2v2,...,tnvn):CBase(v1,v2,v3),objEmbed(v2,v3,vn){派生类部分子集合成员初始化;}

冒号后的成员初始化列表中CBase(v1,v2,v3)是对于基类构造函数的显式调用而objEmbed(v2,v3,vn)是嵌入对象调用自身所隶属的构造函数。语法上基类名、嵌入对象名两者之间的次序可以互换。17

派生类构造函数的形参作用域开始于冒号处结束于构造函数的外层右花括号。因此冒号后构造函数中的实参可以直接采用派生类的形参和其它全局变量名。

如下的对象定义语句:

CDerivedobjd(v1,v2,...,vn); CDerived*pObjd=newCDerived(v1,v2,...,vn);导致派生类含n个形参的构造函数的调用,由此诱发一系列基类构造函数的启动。实参从最晚派生类层层向上传递,直到顶层基类构造函数中的代码首先得到执行。为确保此种传递机制的环环相扣,派生类负责直接基类的初始化。18

派生类缺省的构造函数激发基类相应缺省构造函数的调用。成员函数可以作递归调用。例如:[voidCDerived::Line(){Line();}]是递归调用,递归函数的形参是反复入栈的,隐含的this指针形参出现于递归函数时需要精心设计算法。为避免递归调用发散,派生类CDerived成员函数中显式地调用基类的成员函数。形式为: voidCDerived::Line(){CBase::Line();;...;}

对于虚掉类域分辨符的索引方式m_n,派生类优先使用自身类新增的名称。如果派生类本身未交付这个名称,则上溯索引可访问的基类中的名称。这是优先采用派生类成员名称的支配原则。19[例]

基类和嵌入对象的初始化#include<stdio.h>structSData{longnx;longny;};typedefstructtagPOINT{longx;longy;}POINT;classCPoint:publictagPOINT{public:CPoint(){}CPoint(POINTinitPt){x=initPt.x;y=initPt.y;} };classCBase{ public:CBase(){}~CBase(){delete[]m_p;}protected:CBase(SData*pData){m_n=pData->nx;m_p=newlong[m_n];}20voidLine(){for(intj=0;j<m_n;j++)m_p[j]=j;}protected:longm_n;long*m_p;};classCDerived:publicCBase{public:CDerived(SData*pData,CPointpt); CDerived(){} ~CDerived(){delete[]m_p;} voidLine();voidShow();protected:CPointm_pt; longm_n;long*m_p;};CDerived::CDerived(SData*pData,CPointpt):CBase(pData),m_pt(pt)21{m_n=pData->ny;m_p=newlong[m_n]; }voidCDerived::Line(){CBase::Line();for(intj=0;j<m_n;j++)m_p[j]=j;}voidCDerived::Show(){Line(); longsumx=0;longsumy=0;intk; for(k=0;k<CBase::m_n;k++)su

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论