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

Slides:



Advertisements
Similar presentations
1 基北區 103 學年度免試入學志願選填、 超額比序項目、共同就學區規劃說明 臺北市政府教育局 新北市政府教育局 基隆市政府教育處.
Advertisements

专题复习 --- 走进名著 亲近经典 读完《鲁滨孙漂流记》这本精彩的小说 后,一个高大的形象时时浮现在我的眼 前,他就是勇敢的探险家、航海家鲁滨 孙。他凭着顽强的毅力,永不放弃的精 神,实现了自己航海的梦想。 我仿佛看到轮船甲板上站着这样的一 个人:他放弃了富裕而又舒适的生活, 厌恶那庸庸碌碌的人生,从而开始了一.
北大附中深圳南山分校 倪 杰 2016年8月25日星期四 2016年8月25日星期四 2016年8月25日星期四 Ox y 1 1 y=a x (a>1)
三大评级机构. 金融业行业分类标准 银行证券保险信托 国有商业银行 股份制商业银行 城市商业银行 其他银行机构 例如: 中国平安 中国人寿 太平洋 …… 例如: 国信证券 中信证券 国金证券 西南证券 …… 例如: 安信信托 中信信托 平安信托 …… 金融租赁 财务公司 邮政储蓄 典当 金融担保 外汇、黄金交易.
說 劍 《莊子‧雜篇》─ 第 一 組 賴泊錞 謝孟儒 張維真 羅苡芸
控制方长投下的子公司,需要编制合并报表的演示思路
第六课 遗传与变异 第六课时 性别决定和伴性遗传.
移动应用软件开发技术 第二讲:C++编程基础
判断推理,必须学会这些 主讲老师:小胡胡 2016年3月25日20:00 YY频道:
债券信用评级简介 刘洪芳 鹏元资信评估有限公司. 债券信用评级简介 刘洪芳 鹏元资信评估有限公司.
中国古代诗歌散文欣赏 地点:福建福州 报告人:张华娟.
第四章 继承与派生 Chapter 4 Inheritance and Derivation
第二章 股票市场 第三章 证券投资工具 ----债券 股票概述 股票的发行与流通
债券价值分析 收入资本化法 债券定价原理 债券价值属性 久期、凸度与免疫.
忠孝國小自立午餐老師的叮嚀 教師指導手冊.
第九讲 类与对象 (I)面向对象基础.
第6章 多态性与虚函数.
“08高考化学学业水平(必修科目)测试的命题和教学对策研究”
课标教材下教研工作的 实践与思考 山东临沂市教育科学研究中心 郭允远.
類別與物件 Class & Object.
財務管理 E組 周玉蔻 林宥瑩 倪健育葉欣蓁 白貢帆 林聖峰蔡政華
第八章 类和对象.
第6章 PLC控制系统设计与应用 教学目的与要求:熟悉相关指令的综合应用,掌握PLC控制系统设计方法,掌握PLC程序编制方法,巩固所学内容。
Chapter 5 利率的風險結構與期間結構. Chapter 5 利率的風險結構與期間結構.
4.1 概述 4.2 类与对象的实现 4.3 对象的初始化和析构 4.4 类的包含 4.5 类模板
面向对象技术 练习2 ffh.
第六章 继承性和派生类 胡昊 南京大学计算机系软件所.
第3章 继承和派生.
如何寫工程計畫書 臺北市童軍會考驗委員會 高級考驗營 版.
第12讲 多继承与虚基类 多继承 虚基类.
第八章 类与对象 本章要求: 掌握类的含义与定义格式。 掌握类的无参构造函数、带参构造函数、拷贝构造函数和赋值重载函数的定义格式及作用。
第二章 C++对C 在非面向对象方面的改进 更简洁,更安全.
面向对象程序设计 QQ群: Object-Oriented Programming 汽车学院.
何謂信用風險 信用風險(Credit Risk)又稱為違約風險(Default Risk),是指債務人無法如期支付利息或本金,造成債權人損失的風險。
谭浩强 编著 中国高等院校计算机基础教育课程体系规划教材 C++程序设计.
C/C++/Java 哪些值不是头等程序对象
第二章 词法分析 (Lexical Analysis)
第16章 虛擬與多形 16-1 虛擬函數 16-2 純虛擬函數與抽象類別 16-3 多形 16-4 虛擬繼承與虛擬解構子.
C++面向对象程序设计 谭浩强编著 授课教师:姬广永 QQ: 学习网站:
C++大学基础教程 第11章 多态性 北京科技大学 信息基础科学系 2019/4/8 北京科技大学.
苏 教 版 五 年 级 数 学(上) 用字母表示数 青阳体仁小学 胡春雅.
材料二甲 授課教師:王致傑 老師 (學420、分機5305)
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
C++语言程序设计 C++语言程序设计 第九章 类的特殊成员 第十一组 C++语言程序设计.
C语言程序设计.
第10讲 构造函数和析构函数 构造函数 析构函数 This 指针.
Main() { Dfas Asdfasf fasdfa } #include <stdio.h> void main( ) {
第三章 数据抽象.
白城师范学院经济管理系 成 本 会 计 学 制作:吴威名.
Object-Oriented Programming in C++ 第二章 类和对象
C++语言程序设计 C++语言程序设计 第八章 继承 C++语言程序设计.
面向对象技术 练习 ffh.
C++程序设计基础 主讲人:谢昕 华东交通大学信息工程学院 第十~十二讲 多态性和虚函数 2005年春季学期.
本节内容 对象拷贝 视频提供:昆山爱达人信息技术有限公司.
第九章 物件導向-進階.
第1章 C++面向对象程序设计要点 1.1 函数和函数参数 1.2 输入输出   1.3 类 1.4 抽象类型和模板.
授课老师:龚涛 信息科学与技术学院 2016年3月 教材:《Visual C++程序员成长攻略》 《C++ Builder程序员成长攻略》
C++语言程序设计 C++语言程序设计 第八章 继承 C++语言程序设计.
債券投資.
谭浩强编著 C++面向对象程序设计 授课教师:姬广永 学习网站:
C++语言程序设计 C++语言程序设计 第十章 多态 第十一组 C++语言程序设计.
《数据结构与算法设计》第一部分 面向对象的C++程序设计基础.
§12-5 同方向同频率两个简谐振动的合成 一. 同方向同频率的简谐振动的合成 1. 分振动 : 2. 合振动 : 解析法
JAVA 程式設計與資料結構 第三章 物件的設計.
第2讲 实数的运算及大小比较 考点知识精讲 中考典例精析 举一反三 考点训练.
1.1.3集合的基本运算 全集与补集.
C++语言程序设计(第4版) 第七章 继承与派生 数学与统计科学学院 胡凤珠.
資料結構與C++程式設計進階 C++與資料結構 講師:林業峻 CSIE, NTU 7/ 5, 2010.
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讲 多继承与虚基类 多继承 虚基类