C++语言程序设计七

PPT
  • 阅读 99 次
  • 下载 0 次
  • 页数 75 页
  • 大小 649.000 KB
  • 2022-11-12 上传
  • 收藏
  • 违规举报
  • © 版权认领
下载文档30.00 元 加入VIP免费下载
此文档由【小橙橙】提供上传,收益归文档提供者,本网站只提供存储服务。若此文档侵犯了您的版权,欢迎进行违规举报版权认领
C++语言程序设计七
可在后台配置第一页与第二页中间广告代码
C++语言程序设计七
可在后台配置第二页与第三页中间广告代码
C++语言程序设计七
可在后台配置第三页与第四页中间广告代码
C++语言程序设计七
C++语言程序设计七
还剩10页未读,继续阅读
【这是免费文档,您可以免费阅读】
/ 75
  • 收藏
  • 违规举报
  • © 版权认领
下载文档30.00 元 加入VIP免费下载
文本内容

【文档说明】C++语言程序设计七.ppt,共(75)页,649.000 KB,由小橙橙上传

转载请保留链接:https://www.ichengzhen.cn/view-2183.html

以下为本文档部分文字说明:

2021/7/261(最新整理)C++语言程序设计(清华大学郑莉)七2021/7/262第七章继承与派生清华大学郑莉C++语言程序设计C++语言程序设计清华大学郑莉2021/7/263本章主要内容⚫类的继承⚫类成员的访问

控制⚫单继承与多继承⚫派生类的构造、析构函数⚫类成员的标识与访问⚫深度探索C++语言程序设计清华大学郑莉2021/7/264类的继承与派生⚫保持已有类的特性而构造新类的过程称为继承。⚫在已有类的基础上新增自己的特性而产生新类的过程称为派生

。⚫被继承的已有类称为基类(或父类)。⚫派生出的新类称为派生类。C++语言程序设计清华大学郑莉2021/7/265继承与派生问题举例工具车轿车面包车小汽车卡车旅行车汽车交通工具类的继承与派生C++语言程序设计清华大学郑莉2021/7/266继承与派

生问题举例猴子狮子虎猎豹猫鸟动物类的继承与派生猫科C++语言程序设计清华大学郑莉2021/7/267继承与派生问题举例圆矩形几何形状类的继承与派生C++语言程序设计清华大学郑莉2021/7/268继承与派生问题举例兼职技术人员销售经理管理

人员销售人员雇员类的继承与派生C++语言程序设计清华大学郑莉2021/7/269继承与派生的目的⚫继承的目的:实现代码重用。⚫派生的目的:当新的问题出现,原有程序无法解决(或不能完全解决)时,需要对原有程序进行改造。类的继承与派生C++语言

程序设计清华大学郑莉2021/7/2610派生类的声明class派生类名:继承方式基类名{成员声明;}类的继承与派生C++语言程序设计清华大学郑莉2021/7/2611继承方式⚫不同继承方式的影响主要体现在:–派生类成员

对基类成员的访问权限–通过派生类对象对基类成员的访问权限⚫三种继承方式–公有继承–私有继承–保护继承类成员的访问控制C++语言程序设计清华大学郑莉2021/7/2612公有继承(public)⚫基类的public和protected成员的访问属性在派生类中保持不变,但基类的

private成员不可直接访问。⚫派生类中的成员函数可以直接访问基类中的public和protected成员,但不能直接访问基类的private成员。⚫通过派生类的对象只能访问基类的public成员。类成员的

访问控制C++语言程序设计清华大学郑莉2021/7/2613例7-1公有继承举例classPoint{//基类Point类的定义public://公有函数成员voidinitPoint(floatx=0,floaty=0){this->x=x;this->y=y;}voidmove(float

offX,floatoffY){x+=offX;y+=offY;}floatgetX()const{returnx;}floatgetY()const{returny;}private://私有数据成员floatx,y;};类成员的访问控制classRectangle:publicPoint{//

派生类定义部分public://新增公有函数成员voidinitRectangle(floatx,floaty,floatw,floath){initPoint(x,y);//调用基类公有成员函数this->w=w;this->h=h;}floatgetH

()const{returnh;}floatgetW()const{returnw;}private://新增私有数据成员floatw,h;};14#include<iostream>#include<cmath>usi

ngnamespacestd;intmain(){Rectanglerect;//定义Rectangle类的对象//设置矩形的数据rect.initRectangle(2,3,20,10);rect.move(3,2);//移动矩形位

置cout<<"Thedataofrect(x,y,w,h):"<<endl;//输出矩形的特征参数cout<<rect.getX()<<","<<rect.getY()<<","<<rect.getW()<<","<<rect.getH()<<endl;return0;}15C

++语言程序设计清华大学郑莉2021/7/2616私有继承(private)⚫基类的public和protected成员都以private身份出现在派生类中,但基类的private成员不可直接访问。⚫派生类中的成员函数可以直

接访问基类中的public和protected成员,但不能直接访问基类的private成员。⚫通过派生类的对象不能直接访问基类中的任何成员。类成员的访问控制C++语言程序设计清华大学郑莉2021/7/2

617例7-2私有继承举例classRectangle:privatePoint{//派生类定义部分public://新增公有函数成员voidinitRectangle(floatx,floaty,floatw,floath){init

Point(x,y);//调用基类公有成员函数this->w=w;this->h=h;}voidmove(floatoffX,floatoffY){Point::move(offX,offY);}floatgetX

()const{returnPoint::getX();}floatgetY()const{returnPoint::getY();}floatgetH()const{returnh;}floatgetW()const{r

eturnw;}private://新增私有数据成员floatw,h;};类成员的访问控制#include<iostream>#include<cmath>usingnamespacestd;intmain(){Rectanglerect;//定义Rectangl

e类的对象rect.initRectangle(2,3,20,10);//设置矩形的数据rect.move(3,2);//移动矩形位置cout<<"Thedataofrect(x,y,w,h):"<<endl;cout<<rect.getX()<<","//输出矩形的特征参数<<

rect.getY()<<","<<rect.getW()<<","<<rect.getH()<<endl;return0;}18C++语言程序设计清华大学郑莉2021/7/2619保护继承(protected)⚫基类的public和protected成员都以protected身

份出现在派生类中,但基类的private成员不可直接访问。⚫派生类中的成员函数可以直接访问基类中的public和protected成员,但不能直接访问基类的private成员。⚫通过派生类的对象不能直接访问基类中的任何成员类成员的访问控制C++语言程序设计清

华大学郑莉2021/7/2620protected成员的特点与作用⚫对建立其所在类对象的模块来说,它与private成员的性质相同。⚫对于其派生类来说,它与public成员的性质相同。⚫既实现了数据隐藏,又方便继承,实现代码重用。类成员的访问控制

C++语言程序设计清华大学郑莉2021/7/2621例7-3protected成员举例classA{protected:intx;};intmain(){Aa;a.x=5;//错误}类成员的访问控制classA{protected:in

tx;};classB:publicA{public:voidfunction();};voidB:function(){x=5;//正确}22C++语言程序设计清华大学郑莉2021/7/2623类型兼

容规则⚫一个公有派生类的对象在使用上可以被当作基类的对象,反之则禁止。具体表现在:–派生类的对象可以隐含转换为基类对象。–派生类的对象可以初始化基类的引用。–派生类的指针可以隐含转换为基类的指针。⚫通过基类对象名

、指针只能使用从基类继承的成员类型兼容C++语言程序设计清华大学郑莉2021/7/2624例7-4类型兼容规则举例#include<iostream>usingnamespacestd;classBase

1{//基类Base1定义public:voiddisplay()const{cout<<"Base1::display()"<<endl;}};类型兼容classBase2:publicBase1{//公有派生类Base2定义public:voiddisplay()con

st{cout<<"Base2::display()"<<endl;}};classDerived:publicBase2{//公有派生类Derived定义public:voiddisplay()const{cout<<"Derived::display()"<<end

l;}};voidfun(Base1*ptr){//参数为指向基类对象的指针ptr->display();//"对象指针->成员名"}25intmain(){//主函数Base1base1;//声明Base1类对象Base2base2;//声明Base2类对象Derive

dderived;//声明Derived类对象//用Base1对象的指针调用fun函数fun(&base1);//用Base2对象的指针调用fun函数fun(&base2);//用Derived对象的指针调用fun函数fun(&derived);return0;}运行结果:B0::displ

ay()B0::display()B0::display()26C++语言程序设计清华大学郑莉2021/7/2627基类与派生类的对应关系⚫单继承–派生类只从一个基类派生。⚫多继承–派生类从多个基类派生。⚫多重派生–由一个基类派生出

多个不同的派生类。⚫多层派生–派生类又作为基类,继续派生新的类。单继承与多继承C++语言程序设计清华大学郑莉2021/7/2628多继承时派生类的声明class派生类名:继承方式1基类名1,继承方式2基类名2,...{成员声明;}注意:每一个“继承方式”,只用于限制对紧随

其后之基类的继承。单继承与多继承C++语言程序设计清华大学郑莉2021/7/2629多继承举例classA{public:voidsetA(int);voidshowA()const;private:inta;};classB{public:voidsetB(int);voidshowB()co

nst;private:intb;};classC:publicA,privateB{public:voidsetC(int,int,int);voidshowC()const;privateconst:intc;};单继承与多继承voidA::setA

(intx){a=x;}voidB::setB(intx){b=x;}voidC::setC(intx,inty,intz){//派生类成员直接访问基类的//公有成员setA(x);setB(y);c=z;}//其他函数实现略intmain(){Cobj;obj.setA(5);obj

.showA();obj.setC(6,7,9);obj.showC();//obj.setB(6);错误//obj.showB();错误return0;}30C++语言程序设计清华大学郑莉2021/7/2631继承时的构造函数⚫基类的构造

函数不被继承,派生类中需要声明自己的构造函数。⚫定义构造函数时,只需要对本类中新增成员进行初始化,对继承来的基类成员的初始化,自动调用基类构造函数完成。⚫派生类的构造函数需要给基类的构造函数传递参数派生类的构造、析构函数C++语言程序设计清华大学郑莉2021/

7/2632单一继承时的构造函数派生类名::派生类名(基类所需的形参,本类成员所需的形参):基类名(参数表){本类成员初始化赋值语句;};派生类的构造、析构函数C++语言程序设计清华大学郑莉2021/7/2633单一继承时的构造函数举例#include<iostream>usingnam

ecpacestd;classB{public:B();B(inti);~B();voidprint()const;private:intb;};派生类的构造、析构函数B::B(){b=0;cout<<"B'sde

faultconstructorcalled."<<endl;}B::B(inti){b=i;cout<<"B'sconstructorcalled."<<endl;}B::~B(){cout<<"B'sdestructorcalled."<<endl;}voidB::prin

t()const{cout<<b<<endl;}34classC:publicB{public:C();C(inti,intj);~C();voidprint()const;private:intc;};35C::C(){c

=0;cout<<"C'sdefaultconstructorcalled."<<endl;}C::C(inti,intj):B(i){c=j;cout<<"C'sconstructorcalled."<<endl;}C

::~C(){cout<<"C'sdestructorcalled."<<endl;}voidC::print()const{B::print();cout<<c<<endl;}intmain(){Cobj(5,

6);obj.print();return0;}36C++语言程序设计清华大学郑莉2021/7/2637多继承时的构造函数派生类名::派生类名(参数表):基类名1(基类1初始化参数表),基类名2(基类2初始化参数表),...基类名n(基类n初始化参数表){

本类成员初始化赋值语句;};派生类的构造、析构函数C++语言程序设计清华大学郑莉2021/7/2638派生类与基类的构造函数⚫当基类中声明有缺省构造函数或未声明构造函数时,派生类构造函数可以不向基类构造函数传递参数,也可以不声明,构造派生类的对象时,基类的缺省构造函

数将被调用。⚫当需要执行基类中带形参的构造函数来初始化基类数据时,派生类构造函数应在初始化列表中为基类构造函数提供参数。派生类的构造、析构函数C++语言程序设计清华大学郑莉2021/7/2639多继承且有内嵌对象时的构造函数派生类名::派生类名(形参表):基类名1(参数),

基类名2(参数),...基类名n(参数),新增成员对象的初始化{本类成员初始化赋值语句;};派生类的构造、析构函数C++语言程序设计清华大学郑莉2021/7/2640构造函数的执行顺序1.调用基类构造函数,调用顺序按照它

们被继承时声明的顺序(从左向右)。2.对成员对象进行初始化,初始化顺序按照它们在类中声明的顺序。3.执行派生类的构造函数体中的内容。派生类的构造、析构函数C++语言程序设计清华大学郑莉2021/7/2641拷贝构造函数⚫若建立派生类对象时没有编写拷贝构造函数,编译器会生成一个隐含的拷贝构造函

数,该函数先调用基类的拷贝构造函数,再为派生类新增的成员对象执行拷贝。⚫若编写派生类的拷贝构造函数,则需要为基类相应的拷贝构造函数传递参数。例如:C::C(C&c1):B(c1){…}派生类的构造、析构函数C++语言程序设计清华大学郑莉2021/7/2642例7-4派生类构造函数举例

#include<iostream>usingnamespacestd;classBase1{//基类Base1,构造函数有参数public:Base1(inti){cout<<"ConstructingBase1"<<i<<endl;

}};classBase2{//基类Base2,构造函数有参数public:Base2(intj){cout<<"ConstructingBase2"<<j<<endl;}};classBase3{//基类Base3,构造函数无参数public:Bas

e3(){cout<<"ConstructingBase3*"<<endl;}};派生类的构造、析构函数classDerived:publicBase2,publicBase1,publicBase3{//派生新类Derived,注意基类名的顺序public://派生类的公有成员Derive

d(inta,intb,intc,intd):Base1(a),member2(d),member1(c),Base2(b){}//注意基类名的个数与顺序,//注意成员对象名的个数与顺序private://派生类的私有成员对象Base1member1

;Base2member2;Base3member3;};intmain(){Derivedobj(1,2,3,4);return0;}运行结果:constructingBase22constructingBase11constructingBase3*constructingB

ase13constructingBase24constructingBase3*43C++语言程序设计清华大学郑莉2021/7/2644继承时的析构函数⚫析构函数也不被继承,派生类自行声明⚫声明方法与一般(无继承关系时)类的析构函数相同。⚫不需要显

式地调用基类的析构函数,系统会自动隐式调用。⚫析构函数的调用次序与构造函数相反。派生类的构造、析构函数C++语言程序设计清华大学郑莉2021/7/2645例7-5派生类析构函数举例派生类的构造、析构函数#include<iostream>usingnamespacestd

;classBase1{//基类Base1,构造函数有参数public:Base1(inti){cout<<"ConstructingBase1"<<i<<endl;}~Base1(){cout<<"Dest

ructingBase1"<<endl;}};classBase2{//基类Base2,构造函数有参数public:Base2(intj){cout<<"ConstructingBase2"<<j<<endl;}~Base2(){c

out<<"DestructingBase2"<<endl;}};classBase3{//基类Base3,构造函数无参数public:Base3(){cout<<"ConstructingBase3*"<<endl;}~Base3(){cout<

<"DestructingBase3"<<endl;}};classDerived:publicBase2,publicBase1,publicBase3{//派生新类Derived,注意基类名的顺序public://派生类

的公有成员Derived(inta,intb,intc,intd):Base1(a),member2(d),member1(c),Base2(b){}//注意基类名的个数与顺序,注意成员对象名的个数与顺序private://派生类的私有成员对象Base1member

1;Base2member2;Base3member3;};intmain(){Derivedobj(1,2,3,4);return0;}46C++语言程序设计清华大学郑莉2021/7/2647例7-5运行结果ConstructingBase22Constructi

ngBase11ConstructingBase3*ConstructingBase13ConstructingBase24ConstructingBase3*DestructingBase3DestructingBase2DestructingBase1Destructing

Base3DestructingBase1DestructingBase2C++语言程序设计清华大学郑莉2021/7/2648同名隐藏规则当派生类与基类中有相同成员时:⚫若未强行指名,则通过派生类对象使用的是派生类中的同名成员。⚫如要通过派生类对象访问基类中被隐

藏的同名成员,应使用基类名限定。派生类成员的标识与访问C++语言程序设计清华大学郑莉2021/7/2649例7-6多继承同名隐藏举例(1)派生类成员的标识与访问#include<iostream>us

ingnamespacestd;classBase1{//定义基类Base1public:intvar;voidfun(){cout<<"MemberofBase1"<<endl;}};classBase2{//定义基类Base2public:intvar;

voidfun(){cout<<"MemberofBase2"<<endl;}};classDerived:publicBase1,publicBase2{//定义派生类Derivedpublic:i

ntvar;//同名数据成员voidfun(){cout<<"MemberofDerived"<<endl;}//同名函数成员};intmain(){Derivedd;Derived*p=&d;d.var=1;//对象名.成员名标识d.f

un();//访问Derived类成员d.Base1::var=2;//作用域分辨符标识d.Base1::fun();//访问Base1基类成员p->Base2::var=3;//作用域分辨符标识p->Base2::fun();//访问Base2基类成员return0;

}50C++语言程序设计清华大学郑莉2021/7/2651二义性问题⚫在多继承时,基类与派生类之间,或基类之间出现同名成员时,将出现访问时的二义性(不确定性)——采用虚函数(参见第8章)或同名隐藏规则来解决。⚫当派生类从多个基类派生,而这些基类又从同一个基类派生,则在访问此共同基类中的成员时,

将产生二义性——采用虚基类来解决。派生类成员的标识与访问C++语言程序设计清华大学郑莉2021/7/2652二义性问题举例(一)classA{public:voidf();};classB{public

:voidf();voidg()};classC:publicA,piblicB{public:voidg();voidh();};如果定义:Cc1;则c1.f()具有二义性而c1.g()无二义性(同名隐藏)派生类成员的标识与访问C++语言程序设计清华大学郑莉2021/7/2653

二义性的解决方法⚫解决方法一:用类名来限定c1.A::f()或c1.B::f()⚫解决方法二:同名隐藏在C中声明一个同名成员函数f(),f()再根据需要调用A::f()或B::f()派生类成员的标识与访问C++语言程

序设计清华大学郑莉2021/7/2654二义性问题举例(二)classB{public:intb;}classB1:publicB{private:intb1;};classB2:publicB{private:int

b2;};classC:publicB1,publicB2{public:intf();private:intd;}派生类成员的标识与访问有二义性:Cc;c.bc.B::b无二义性:c.B1::bc.B2::bC++语言程序设计清华大学郑莉2021/7/26

55虚基类⚫虚基类的引入–用于有共同基类的场合⚫声明–以virtual修饰说明基类例:classB1:virtualpublicB⚫作用–主要用来解决多继承时可能发生的对同一基类继承多次而产生的二义性问题.–为最远的派生类提供唯一的基类成员,而不重复产生多次拷贝⚫注意:–

在第一级继承时就要将共同基类设计为虚基类。C++语言程序设计清华大学郑莉2021/7/2656虚基类举例classB{public:intb;};classB1:virtualpublicB{public:intb1;};classB2:v

irtualpublicB{public:intb2;};classC:publicB1,publicB2{public:floatd;};下面的访问是正确的:Ccobj;cobj.b;虚基类C++语言程序设计清华大学郑莉2021/7/2657例

7-8虚基类举例虚基类DerivedBase0::var0:intBase1::var1:intBase2::var2:intvar:intBase0::fun0():voidfun():voidBase1+var1:intBase2+var2:intDerived+var:int

+fun():void<<virtual>>Base0+var0:int+fun0():void#include<iostream>usingnamespacestd;classBase0{//定义基类Base0public:intvar0;voidfun0(){cout<<"M

emberofBase0"<<endl;}};classBase1:virtualpublicBase0{//定义派生类Base1public://新增外部接口intvar1;};classBase2:virtualpu

blicBase0{//定义派生类Base2public://新增外部接口intvar2;};58classDerived:publicBase1,publicBase2{//定义派生类Derivedpublic://新增外部接口intvar;voidfun(){cout<<"MemberofDe

rived"<<endl;}};intmain(){//程序主函数Derivedd;//定义Derived类对象dd.var0=2;//直接访问虚基类的数据成员d.fun0();//直接访问虚基类的函数成员return0;}59C++语言程序设计清

华大学郑莉2021/7/2660虚基类及其派生类构造函数⚫建立对象时所指定的类称为最(远)派生类。⚫虚基类的成员是由最派生类的构造函数通过调用虚基类的构造函数进行初始化的。⚫在整个继承结构中,直接或间接继承虚基类的所有派生类,都必须在构造函数的成员初始化表中给出对

虚基类的构造函数的调用。如果未列出,则表示调用该虚基类的默认构造函数。⚫在建立对象时,只有最派生类的构造函数调用虚基类的构造函数,该派生类的其他基类对虚基类构造函数的调用被忽略。虚基类C++语言程序设计清华大学郑莉

2021/7/2661有虚基类时的构造函数举例虚基类#include<iostream>usingnamespacestd;classBase0{//定义基类Base0public:Base0(intvar):var0(var){}intvar0;voidfun0()

{cout<<"MemberofBase0"<<endl;}};classBase1:virtualpublicBase0{//定义派生类Base1public://新增外部接口Base1(intvar):Base0(var){}intvar1;};classBase2:virtualp

ublicBase0{//定义派生类Base2public://新增外部接口Base2(intvar):Base0(var){}intvar2;};classDerived:publicBase1,publicBase2{//定义

派生类Derivedpublic://新增外部接口Derived(intvar):Base0(var),Base1(var),Base2(var){}intvar;voidfun(){cout<<"MemberofDerived"<<endl;}};in

tmain(){//程序主函数Derivedd(1);//定义Derived类对象dd.var0=2;//直接访问虚基类的数据成员d.fun0();//直接访问虚基类的函数成员return0;}62C++语言程序设计清华大

学郑莉2021/7/2663组合与继承⚫组合与继承:通过已有类来构造新类的两种基本方式⚫组合:B类中存在一个A类型的内嵌对象–有一个(has-a)关系:表明每个B类型对象“有一个”A类型对象–A类型对象与B类型对象是部分与整体关系–B类型的接口不会直接作为A类型的接口深度探索C++语

言程序设计清华大学郑莉2021/7/2664“has-a”举例classEngine{//发动机类public:voidwork();//发动机运转……};classWheel{//轮子类public:voidroll();//轮子转动…

…};classAutomobile{//汽车类public:voidmove();//汽车移动private:Engineengine;//汽车引擎Wheelwheels[4];//4个车轮……};⚫意义–一辆汽车有一

个发动机–一辆汽车有四个轮子⚫接口–作为整体的汽车不再具备发动机的运转功能,和轮子的转动功能,但通过将这些功能的整合,具有了自己的功能——移动深度探索C++语言程序设计清华大学郑莉2021/7/2665公有继承的意义⚫公有继承:A类是B类的公有基类–是一个(is-a)关系:表明每个B类型对象

“是一个”A类型对象–A类型对象与B类型对象是一般与特殊关系⚫回顾类的兼容性原则:在需要基类对象的任何地方,都可以使用公有派生类的对象来替代–B类型对象包括A类型的全部接口深度探索C++语言程序设计清华大学郑莉2021/7/266

6“is-a”举例classTruck:publicAutomobile{//卡车public:voidload(…);//装货voiddump(…);//卸货private:……};classPumper:publicAutomobile{//消防车

public:voidwater();//喷水private:……};⚫意义–卡车是汽车–消防车是汽车⚫接口–卡车和消防车具有汽车的通用功能(移动)–它们还各自具有自己的功能(卡车:装货、卸货;消防车:喷水)深度探索C++语

言程序设计清华大学郑莉2021/7/2667派生类对象的内存布局⚫派生类对象的内存布局–因编译器而异–内存布局应使类型兼容规则便于实现⚫一个基类指针,无论其指向基类对象,还是派生类对象,通过它来访问一个基类中定义的数据成员,都可以用相同的步骤⚫不同情况下的内存布局–单继承:基类数据在前

,派生类新增数据在后–多继承:各基类数据按顺序在前,派生类新增数据在后–虚继承:需要增加指针,间接访虚基类数据深度探索C++语言程序设计清华大学郑莉2021/7/2668单继承情形classBase{…};classDerived:publicBase{…};Derived*pd

=newDerived();Base*pb=pd;Derived类型指针pd转换为Base类型指针时,地址不需要改变Base类数据成员Derived类新增数据成员pb,pdDerived对象深度探索C++语言程序设计清华大学郑莉2021/7/2669多继承情形classBase

1{…};classBase2{…};classDerived:publicBase1,publicBase2{…};Derived*pd=newDerived();Base1*pb1=pd;Base2*pb2=pd;Derived类型指针pd转换为Base2类型指针时

,原地址需要增加一个偏移量Base1类数据成员Base2类数据成员pb1,pdDerived对象pb2Derived类新增数据成员深度探索C++语言程序设计清华大学郑莉2021/7/2670虚拟继承情形classBase0{…};classBase1

:virtualpublicBase0{…};classBase2:virtualpublicBase0{…};classDerived:publicBase1,publicBase2{…};Derived*pd=newDeriv

ed();Base1*pb1=pd;Base2*pb2=pd;Base0*pb0=pb1;Base0类数据成员Base1类新增数据成员pb1,pdBase0指针Base1类新增数据成员Base0指针Derived对象pb2pb0通过指针间接访问虚基类的数据成员深度探索C++语言程序设计清华大

学郑莉2021/7/2671基类向派生的转换⚫基类向派生类的转换–基类指针可以转换为派生类指针–基类引用可以转换为派生类引用–需要用static_cast显式转换⚫例:Base*pb=newDerived();Derived*pd=static_cast<Derived*>(p

d);Derivedd;Base&rb=d;Derived&rb=static_cast<Derived&>(rb);深度探索C++语言程序设计清华大学郑莉2021/7/2672类型转换时的注意事项(1)⚫基类对象一般无法被显式转换为派生

类对象–对象到对象的转换,需要调用构造函数创建新的对象–派生类的拷贝构造函数无法接受基类对象作为参数⚫执行基类向派生类的转换时,一定要确保被转换的指针和引用所指向或引用的对象符合转换的目的类型:–对于Derived*pd=static_cast<Derived*>(pb);–一定要保

证pb所指向的对象具有Derived类型,或者是Derived类型的派生类。深度探索C++语言程序设计清华大学郑莉2021/7/2673类型转换时的注意事项(2)⚫如果A类型是B类型的虚拟基类,A类型指针无法通过static_cast隐含转换为B类型的指针–可以结合虚继承情况下的

对象内存布局,思考为什么不允许这种转换⚫void指针参加的转换,可能导致不可预期的后果:–例:(Base2是Derived的第二个公共基类)Derived*pd=newDerived();void*pv=pd;//将Derived指针转换为void指针B

ase2*pb=static_cast<Base2*>(pv);–转换后pb与pd有相同的地址,而正常的转换下应有一个偏移量–结论:有void指针参与的转换,兼容性规则不适用⚫更安全更灵活的基类向派生类转换方式——dynami

c_cast,将在下一讲介绍深度探索C++语言程序设计清华大学郑莉2021/7/2674小结与复习建议⚫主要内容–类的继承、类成员的访问控制、单继承与多继承、派生类的构造和析构函数、类成员的标识与访问⚫达到的目标–理

解类的继承关系,学会使用继承关系实现代码的重用。⚫实验任务–实验七C++语言程序设计清华大学郑莉2021/7/2675

小橙橙
小橙橙
文档分享,欢迎浏览!
  • 文档 25747
  • 被下载 7
  • 被收藏 0
相关资源
广告代码123
若发现您的权益受到侵害,请立即联系客服,我们会尽快为您处理。侵权客服QQ:395972555 (支持时间:9:00-21:00) 公众号
Powered by 太赞文库
×
确认删除?