第12讲 多继承与虚基类 多继承 虚基类.

Slides:



Advertisements
Similar presentations
专题复习 --- 走进名著 亲近经典 读完《鲁滨孙漂流记》这本精彩的小说 后,一个高大的形象时时浮现在我的眼 前,他就是勇敢的探险家、航海家鲁滨 孙。他凭着顽强的毅力,永不放弃的精 神,实现了自己航海的梦想。 我仿佛看到轮船甲板上站着这样的一 个人:他放弃了富裕而又舒适的生活, 厌恶那庸庸碌碌的人生,从而开始了一.
Advertisements

中国古代诗歌散文欣赏 地点:福建福州 报告人:张华娟.
第8章 继承和派生 8.1 继承与派生 8.2 派生类对基类成员的访问 8.3 派生类的构造函数与析构函数 8.4 多重继承与虚基类.
课程 要求 参考 书目 课程 内容 课程 练习.
面向对象的C++程序设计基础 第 4 章 继承与派生.
第四章 继承与派生 Chapter 4 Inheritance and Derivation
第10章 虚函数与多态性.
第6章 多态性与虚函数.
7.2 访问控制 —— 公有继承 公有继承练习 //Point.h #ifndef _POINT_H #define _POINT_H class Point { //基类Point类的定义 public: //公有函数成员 void initPoint(float x = 0, float.
内容提要 代码重用 类的继承 多态 抽象类 多重继承 虚拟继承. 常宝宝 北京大学计算机科学与技术系
计算机可视化编程 基于Visual C++6.0的面向对象编程 第 四 讲 主讲教师:隋振                学时:32.
C++面向对象程序设计 第八章 继承和派生.
第12章 组合与继承 欢迎辞 第14次见面!.
第四章 继承和派生类 汽车 专用汽车 运输汽车 货车 客车 消防车 洒水车 最普遍、最一般,可以自行驱动 含有汽车的特性,同时与汽车有不同
第14章 c++中的代码重用.
C++语言程序设计 第七章 继承与派生 清华大学 郑 莉.
C++ 面对对象程序设计 授课老师:.
財務管理 E組 周玉蔻 林宥瑩 倪健育葉欣蓁 白貢帆 林聖峰蔡政華
第6章 多态性与虚函数.
Chapter 5 利率的風險結構與期間結構. Chapter 5 利率的風險結構與期間結構.
面向对象技术 练习2 ffh.
第六章 继承性和派生类 胡昊 南京大学计算机系软件所.
第3章 继承和派生.
如何寫工程計畫書 臺北市童軍會考驗委員會 高級考驗營 版.
第11讲 类的继承 1. 类的继承的概念 2. 类的单继承机制 3. 单继承中的构造函数和析构函数.
辅导课程六.
第八章 类与对象 本章要求: 掌握类的含义与定义格式。 掌握类的无参构造函数、带参构造函数、拷贝构造函数和赋值重载函数的定义格式及作用。
第1章 C++基础.
第一单元 初识C程序与C程序开发平台搭建 ---观其大略
面向对象程序设计 QQ群: Object-Oriented Programming 汽车学院.
第六章 数据抽象-类 胡昊 南京大学计算机系软件所.
何謂信用風險 信用風險(Credit Risk)又稱為違約風險(Default Risk),是指債務人無法如期支付利息或本金,造成債權人損失的風險。
第八章 继承与派生 丘志杰 电子科技大学 计算机学院 软件学院.
第十一章 继承和派生. 主讲教师:全红艳 第十一章 继承和派生.
C/C++/Java 哪些值不是头等程序对象
第16章 虛擬與多形 16-1 虛擬函數 16-2 純虛擬函數與抽象類別 16-3 多形 16-4 虛擬繼承與虛擬解構子.
C++大学基础教程 第9章 继承与派生 北京科技大学.
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
C++面向对象程序设计 谭浩强编著 授课教师:姬广永 QQ: 学习网站:
第11讲 类的继承 1. 类的继承的概念 2. 类的单继承机制 3. 单继承中的构造函数和析构函数.
第12讲 多继承与虚基类 多继承 虚基类.
内容 构造函数 析构函数 对象数组 对象指针 this指针 const数据保护. 类和对象的使用 潘荣江 山东大学.
C++复习3 ----类的继承与派生.
C#面向对象程序设计 $6 深入理解类.
C++语言程序设计 第四章 类与对象.
第13讲 多态 友员函数 多态性与虚函数 纯虚函数和抽象类.
补课.
C++程序设计— 多态与虚函数 主讲:资讯系张玉宏.
第10讲 构造函数和析构函数 构造函数 析构函数 This 指针.
C++语言程序设计 C++语言程序设计 第九章 类的特殊成员 第十一组 C++语言程序设计.
本节内容 类成员的访问控制 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
Object-Oriented Programming in C++ 第二章 类和对象
C++语言程序设计 C++语言程序设计 第八章 继承 C++语言程序设计.
面向对象技术 练习 ffh.
C++程序设计基础 主讲人:谢昕 华东交通大学信息工程学院 第十~十二讲 多态性和虚函数 2005年春季学期.
C++语言程序设计 C++语言程序设计 第八章 继承 C++语言程序设计.
C++语言程序设计教程 第8章 继承与派生 第8章 继承与派生 制作人:杨进才.
辅导课程十五.
授课老师:龚涛 信息科学与技术学院 2016年3月 教材:《Visual C++程序员成长攻略》 《C++ Builder程序员成长攻略》
C++语言程序设计 C++语言程序设计 第十一章 异常处理 C++语言程序设计.
谭浩强编著 C++面向对象程序设计 授课教师:姬广永 学习网站:
C++语言程序设计 C++语言程序设计 第十章 多态 第十一组 C++语言程序设计.
C++语言程序设计 C++语言程序设计 第八章 继承 C++语言程序设计.
C++语言程序设计 C++语言程序设计 第九章 类的特殊成员 第十一组 C++语言程序设计.
C++语言程序设计 C++语言程序设计 第九章 类的特殊成员 第十一组 C++语言程序设计.
§12-5 同方向同频率两个简谐振动的合成 一. 同方向同频率的简谐振动的合成 1. 分振动 : 2. 合振动 : 解析法
第十二讲 继承 与 派生.
C++语言程序设计(第4版) 第七章 继承与派生 数学与统计科学学院 胡凤珠.
C++语言程序设计 C++语言程序设计 第九章 类的特殊成员 第十一组 C++语言程序设计.
2.2.2双曲线的简单几何性质 海口市灵山中学 吴潇.
Presentation transcript:

第12讲 多继承与虚基类 多继承 虚基类

学习目标 理解多继承的相关概念; 掌握多继承派生类的构造函数 掌握虚基类的相关概念和定义方法 理解虚基类构造函数的定义方法

多继承 可以用多个基类来派生一个类。 D 多继承是单继承的扩展 A B C 派生类中新定义的成员

声明多重继承的方法 class 派生类名 : [继承方式]基类名1 , [继承方式]基类名2, ...,[继承方式]基 类名n { 派生类成员声明; };

class 类名:<Access>类名1,..., <Access>类名n { 例如: class 类名:<Access>类名1,..., <Access>类名n { private: ...... ; //私有成员说明; public: ...... ; //公有成员说明; protected: ...... ; //保护的成员说明; }; 继承方式 class D: public A, protected B, private C { ....//派生类中新增加成员 }; 第一章 VC集成开发环境

class A { public: displayA() { cout<<a; } private: int a; }; class B { public: displayB() { cout<<b; } private: int b; class C:public A,public B { public: displayC() { cout<<c; } private: int c;

多继承结构 A int a; void DisplayA( ); B int b; void DisplayB( ); C int a; int c; void DisplayA( ); void DisplayB( ); void DisplayC( );

B b1(10,20); b1.ShowB(); class A{ int x1,y1; public: A(int a,int b) { x1=a; y1=b; } void ShowA(void){ cout<<"A.x="<<x1<<'\t'<<"A.y="<<y1<<endl; } }; class B{int x2,y2; public: B(int a,int b) {x2=a; y2=b; } void ShowB(void){ cout<<"B.x="<<x2<<'\t'<<"B.y="<<y2<<endl; } class C:public A,private B{ int x,y; public: C(int a,int b,int c,int d,int e,int f):A(a,b),B(c,d) {x=e; y=f; } void ShowC(void){cout<<"C.x="<<x<<'\t'<<"C.y="<<y<<endl; ShowA();ShowB(); } void main(void) { C c(1,2,3,4,5,6); c.ShowC(); c.ShowA (); c.ShowB (); } 公有派生 私有派生 仍为公有 成为私有 B b1(10,20); b1.ShowB(); 非法,私有类外不可调用 第一章 VC集成开发环境

多继承派生类的构造函数 派生类构造函数的调用顺序如下: 基类的构造函数 基类子对象的构造函数 派生类的构造函数 多继承下的构造函数和析构函数与单继承下的构造函数和析构函数是相似的,派生类的构造函数需要对基类成员、内嵌子对象和新增成员进行初始化。 构造函数不能被继承,派生类的构造函数必须调用基类的构造函数来初始化基类成员和基类子对象。 派生类构造函数的调用顺序如下: 基类的构造函数 基类子对象的构造函数 派生类的构造函数

{ public: A(int aa=0) { a=aa; } private: int a; }; class B class A { public: A(int aa=0) { a=aa; } private: int a; }; class B { public: B(int bb=0) { b=bb; } private: int b; class C:public A,public B { public:C(int a1,int a2,int b1,int b2,int cc):A(a1), B(b1), a(a2), b(b2){ c=cc; } private: A a; B b; int c; 构造函数 10

基类子对象举例 class Derived: public Base2, public Base1{ int z; Base1 b1,b2; Derived(int a,int b):Base1(a),Base2(20), b1(200),b2(a+b) {z=b; cout<<"调用派生类的构造函数!\n";} ~Derived( ){cout<<"调用派生类的析构函数!\n";} }; void main(void) { Derived c(100,200); } 基类子对象 基类子对象构造 基类成员构造 基类成员构造用基类名, 基类子对象构造用对象名

当撤销派生类对象时,析构函数的调用正好相反。 class B:public A{ int y; A a1; public: B(int a, int b):A(a),a1(3){y=b;} ....... }; 基类的构造函数 基类子对象的构造函数 派生类的构造函数 当撤销派生类对象时,析构函数的调用正好相反。 第一章 VC集成开发环境

public: Base1(int a){ x=a;cout<<"调用基类1的构造函数!\n"; } class Base1 { int x; public: Base1(int a){ x=a;cout<<"调用基类1的构造函数!\n"; } ~Base1( ){ cout<<"调用基类1的析构函数!\n"; } }; class Base2 { int y; public: Base2(int a){ y=a;cout<<"调用基类2的构造函数!\n"; } ~Base2( ){ cout<<"调用基类2的析构函数!\n"; } class Derived:public Base2, public Base1{ int z; public: Derived(int a,int b):Base1(a),Base2(20) {z=b; cout<<"调用派生类的构造函数!\n";} ~Derived( ){cout<<"调用派生类的析构函数!\n";} void main(void) { Derived c(100,200); } 先说明基类2 调用基类2的构造函数 调用基类1的构造函数 调用派生类的构造函数 调用派生类的析构函数 调用基类1的析构函数 调用基类2的析构函数 第一章 VC集成开发环境

public: Base1(int a) {x=a;cout<<"调用基类1的构造函数!\n";} class Base1 { int x; public: Base1(int a) {x=a;cout<<"调用基类1的构造函数!\n";} ~Base1( ) {cout<<"调用基类1的析构函数!\n";} }; class Base2 { int y; public: Base2(int a) {y=a;cout<<"调用基类2的构造函数!\n";} ~Base2( ){cout<<"调用基类2的析构函数!\n";} class Derived:public Base2, public Base1{ int z; Base1 b1,b2; public: Derived(int a,int b):Base1(a),Base2(20), b1(200),b2(a+b) {z=b; cout<<"调用派生类的构造函数!\n";} ~Derived( ){cout<<"调用派生类的析构函数!\n";} void main(void) { Derived c(100,200); } 第一章 VC集成开发环境

运行结果 调用基类2的构造函数 说明基类1的对象b1,b2 调用基类1的构造函数 调用基类1的构造函数 调用基类1的构造函数 调用派生类的构造函数 调用派生类的析构函数 调用基类1的析构函数 调用基类1的析构函数 调用基类1的析构函数 调用基类2的析构函数

{ public: B1(int i) { cout<<"B1 "<<i<<endl; } }; class B1 { public: B1(int i) { cout<<"B1 "<<i<<endl; } }; class B2 { public: B2(int j) { cout<<"B2 "<<j<<endl; } }; class B3 { public: B3( ) { cout<<"B3 *"<<endl; } }; class C:public B2,public B1,public B3 {public: C(int a,int b,int c,int d):B1(a),memB2(d),memB1(c),B2(b){ } private: B1 memB1; B2 memB2; B3 memB3; }; void main() { C obj(1,2,3,4); } 16

多继承引起的二义性问题 class A { public: void display() { cout<<"A"<<endl; } }; class B { public: void display() { cout<<"B"<<endl; } class C: public A, public B { }; void main() { C c; c.display(); }

多继承引起的二义性问题 A void display(); B C void A::display(); void B::display(); C c; c.A::display(); c.B::display(); C c; c.display();

v.x=5; v. A::x=5; 多继承引起的二义性问题 public D v; 派生类对象 D A x A() B B() 产生了冲突 用类作用符限定

这时,可以利用类作用域符::来指明数据或函数的来源。 class A{ public: int x; void Show(){cout <<"x="<<x<<'\n';} A(int a=0){x=a;} }; class B{ B(int a=0){x=a;} class C:public A,public B{ int y; public: void Setx(int a){ x=a;} //c1对象中有两个x成员 void Sety(int b){y=b;} int Gety() {return y;} void main(void) { C c1; c1.Show(); //c1对象中有两个Show()函数 } 这时,可以利用类作用域符::来指明数据或函数的来源。 如:A::x=a; c1.B::Show();

第11讲 类的继承(二) 多继承 虚基类

虚基类 x A() y B() x A() z C() x A() dx D() x A() z C() y B() 类B 是类A的派生类 类C 是类A的派生类 B类 类D 是类B和类C的派生类 这样,类D中就有两份类A的拷贝 类A拷贝 x A() y B() x A() z C() C类 x A() A类 D类 B类 C类

虚基类 这种同一个公共的基类在派生类中产生多个拷贝,不仅多占用了存储空间,而且可能会造成多个拷贝中的数据不一致和模糊的引用。 D d; dx D() x A() z C() y B() 这种同一个公共的基类在派生类中产生多个拷贝,不仅多占用了存储空间,而且可能会造成多个拷贝中的数据不一致和模糊的引用。 类A拷贝 B类 类A拷贝 C类 D d; d.x=10; //模糊引用 D类

例子 x A() y B() x A() z C() 模糊引用,错误! dx D() class A{ public: int x; A(int a=0) { x=a;} }; class B:public A{ public: int y; B(int a=0,int b=0):A(a) { y=b;} class C:public A{ public: int z; C(int a,int c):A(a){ z=c; } class D:public B,public C{ public: int dx; D(int a1,int b,int c,int d,int a2):B(a1,b),C(a2,c) { dx=d;} void main(void) { D d1(10,20,30,40,50); cout<<d1.x<<endl; } A() y b=20 B() x a2=50 A() z c=30 C() 模糊引用,错误! dx dx=40 D() D类

虚基类 在多继承中,若使公共基类在派生类中只有一个拷贝,则可将这种基类说明为虚基类。虚基类的作用:可以使得在继承间接共同基类时只保留一份成员。 在派生类的定义中,只要在基类的类名前加上关键字virtual,就可以将基类说明为虚基类。 class B:public virtual A{ public: int y; B(int a=0, int b=0 ):A(b) { y=a;} }; 25

void display( ) { cout<<a<<endl; } }; class A{ public: int a; void display( ) { cout<<a<<endl; } }; class B:virtual public A { }; class C:virtual public A { }; class D:virtual public A { }; class E:public B,public C,public D{ }; void main( ) { E e; e.a=1; e.display(); } 为了保证虚基类的成员在派生类中只继承一次,应当在该基类的所有直接派生类中声明为虚基类。 26

一份拷贝,在D( )的构造函数中直接调用A() x A() x A() y B() x A() z C() x A() y B() z C() dx D() 由虚基类派生出的对象初始化时,直接调用虚基类的构造函数。因此,若将一个类定义为虚基类,则一定有正确的构造函数可供所有派生类调用。 A类 B类 C类 D类 第一章 VC集成开发环境

虚基类的构造函数 如果在虚基类中定义了带参数的构造 函数,且没有默认构造函数,则在其 所有直接或间接派生类中,都必须通 过初始化表对虚基类进行初始化。

class A {public: A(int aa) { a=aa; } private: int a; }; class B:virtual public A {public: B(int aa,int bb):A(aa) { b=bb; } private: int b; class C:virtual public A {public: C(int aa,int cc):A(aa) { c=cc; } private: int c; class D:public B,public C {public: D(int aa,int bb,int cc,int dd):A(aa),B(aa,bb),C(aa,cc) { d=dd; } private: int d;

没有对虚基类构造函数的调用,用缺省的构造函数 class A{ public: int x; A(int a=0) { x=a;} }; class B:public virtual A{ public: int y; B(int a=0,int b=0): A(a) {y=b;} class C:public virtual A{ public: int z; C(int a=0,int c=0):A(a){z=c; } class D:public B,public C{ public: int dx; D(int a1,int b,int c,int d,int a2):B(a1,b),C(a2,c) {dx=d;} void main(void) { D d1(10,20,30,40,50); cout<<d1.x<<endl; d1.x=400; cout<<d1.y<<endl; } 400 20 50 400 20 直接在派生类中调用虚基类的构造函数 , A(a2) 没有对虚基类构造函数的调用,用缺省的构造函数

第12讲 多继承与虚基类 多继承 虚基类