带有虚函数的情况。

下面情况编译器也会在需要的时候为其合成。

1.如果一个类自己声明为虚函数.

 1 #include<iostream>
2 using namespace std;
3 class Base
4 {
5 public:
6 virtual void foo(){}
7 };
8 int main()
9 {
10 Base b;
11 while (1);
12 return 0;
13 }

分析:由于类中声明了虚函数,所以编译器会为其合成一个出来,这个合成的默认构造函数的作用是用来保存虚函数表的指针。

2.如果一个类继承了带虚函数的类。

1)单继承情况

 1 #include<iostream>
2 using namespace std;
3 class Base
4 {
5 public:
6 virtual void foo(){}
7 };
8 class Deprive:public Base
9 {
10 public:
11 void foo() override {
12
13 }
14 };
15 int main()
16 {
17 Deprive d;
18 while (1);
19 return 0;
20 }

分析:由于继承关系,所以类Base的虚函数属性也被Deprive继承下来,由于类Deprive中没有自己的构造函数,所以此时编译器会为其合成一个出来,同样,在这个合成的默认构造函数中,所做的工作是保存虚函数表的指针。(这里通过sizeof(Deprive)可以看出,类的大小还是4。也就是说,类Base和类Deprive共用了一个虚函数表指针).

2)多继承情况

 1 #include<iostream>
2 using namespace std;
3 class Base1
4 {
5 public:
6 virtual void foo1(){}
7 virtual void foo1(){}
8 };
9 class Base2
10 {
11 public:
12 virtual void func1(){}
13 virtual void func2(){}
14 };
15 class Deprive:public Base1,public Base2
16 {
17 public:
18 void foo1() override {}
19 void func2()override {}
20 virtual void My_HanShu(){}
21 };
22 int main()
23 {
24 Deprive d;
25 while (1);
26 return 0;
27 }

分析:同样,在多继承体系中,编译器会为类Deprive合成一个默认的构造函数出来,用来保存虚函数表的地址,这里通过sizeof(Deprive)可以看出大小为8字节,所以在默认的构造函数中有两个虚函数表指针,一个是与基类共用的,另一个是另外一个基类的。

注:多继承时,按照继承的顺序,子类的虚函数表指针与第一个继承的父类共用。

3.类派生自一个继承链串。

 1 #include<iostream>
2 using namespace std;
3 class Base1
4 {
5 public:
6 virtual void foo1(){}
7 };
8 class Base2:public Base1
9 {
10 public:
11 };
12 class Deprive:public Base2
13 {
14 public:
15 };
16 int main()
17 {
18 Deprive d;
19 while (1);
20 return 0;
21 }

分析:这种情况本质没有什么区别,只要基类有虚函数在,那么不管他的派生类的链串有多长,虚函数的属性就会被继承,虚函数属性被继承了,接下来的分析就和前面相同了。

下面是C++对象模型中的例子(我添加了一些代码以便运行的效果):(书P45页)

 1 #include<iostream>
2 using namespace std;
3 class Widget
4 {
5 public:
6 virtual void flip()=0;
7 };
8 void flip(Widget& widget)
9 {
10 widget.flip();
11 }
12 class Bell:public Widget
13 {
14 public:
15 void flip()
16 {
17 cout << "Bell" << endl;
18 }
19 };
20 class Whistle:public Widget
21 {
22 public:
23 void flip()
24 {
25 cout << "Whistle" << endl;
26 }
27 };
28 void foo()
29 {
30 Bell b;
31 Whistle w;
32 flip(b);
33 flip(w);
34 }
35 int main()
36 {
37 foo();
38 while (1);
39 return 0;
40 }

分析:由于编译器在合成的默认构造函数中添加了虚函数表指针,所以接下来在函数void flip(Widget& widget)中的调用是通过虚函数表走的。

widget.flip()的编译器视角就是:*widget.vptr[1](&widget)  (关于布局写法以后再深谈)。

C++构造函数语义学(二)(基于C++对象模型)的更多相关文章

  1. C++构造函数语义学(一)(基于C++对象模型)

    如果一个类没有自己的构造函数,编译器会在需要的时候为其合成一个出来,俗称:合成默认构造函数.但是请注意是在需要的时候,并不是所有情况. 请看下面代码: 1 #include<iostream&g ...

  2. C++构造函数语义学(三)(基于C++对象模型)

    带有虚基类的情况. 1 #include<iostream> 2 using namespace std; 3 class X 4 { 5 public: 6 int i; 7 }; 8 ...

  3. 构造函数语义学之Copy Constructor构建操作(2)

    二.详述条件 3 和 4 那么好,我又要问大家了,条件1 和 2比较容易理解.因为member object或 base class 含有copy constructor.那么member objec ...

  4. VSTO学习笔记(二)Excel对象模型

    原文:VSTO学习笔记(二)Excel对象模型 上一次主要学习了VSTO的发展历史及其历代版本的新特性,概述了VSTO对开发人员的帮助和效率提升.从这次开始,将从VSTO 4.0开始,逐一探讨VSTO ...

  5. 构造函数语义学——Copy Constructor 篇

    构造函数语义学--Copy Constructor 篇 本文主要介绍<深度探索 C++对象模型>之<构造函数语义学>中的 Copy Constructor 构造函数的调用时机 ...

  6. CRL快速开发框架系列教程二(基于Lambda表达式查询)

    本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...

  7. Android消息推送(二)--基于MQTT协议实现的推送功能

    国内的Android设备,不能稳定的使用Google GCM(Google Cloud Messageing)消息推送服务. 1. 国内的Android设备,基本上从操作系统底层开始就去掉了Googl ...

  8. word2vec原理(二) 基于Hierarchical Softmax的模型

    word2vec原理(一) CBOW与Skip-Gram模型基础 word2vec原理(二) 基于Hierarchical Softmax的模型 word2vec原理(三) 基于Negative Sa ...

  9. 构造函数语义学——Default Constructor篇

    构造函数语义学--Default Constructor 篇 这一章原书主要分析了:编译器关于对象构造过程的干涉,即在对象构造这个过程中,编译器到底在背后做了什么 这一章的重点在于 default c ...

随机推荐

  1. P7990-[USACO21DEC]Closest Cow Wins S【堆,贪心】

    正题 题目链接:https://www.luogu.com.cn/problem/P7990 题目大意 数轴上有\(k\)个点是草地,每个草地有不同收益,\(m\)个点是地方的点,现在你要放置\(n\ ...

  2. js中的jQuery Validate增加手机号码验证

    $.validator.addMethod("isPhone", function(value,element) { var length = value.length; var ...

  3. 再谈多线程模型之生产者消费者(基础概念)(c++11实现)

    0.关于 为缩短篇幅,本系列记录如下: 再谈多线程模型之生产者消费者(基础概念)(c++11实现)[本文] 再谈多线程模型之生产者消费者(单一生产者和单一消费者)(c++11实现) 再谈多线程模型之生 ...

  4. 【LeetCode】1418. 点菜展示表 Display Table of Food Orders in a Restaurant

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 字典统计边的次数 日期 题目地址:https://le ...

  5. 【LeetCode】954. Array of Doubled Pairs 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 日期 题目地址:https://leetcode.c ...

  6. C. The Meaningless Game

    C. The Meaningless Game 题目链接 题意 给你两个数,开始都为1,然后每轮可以任选一个k,一边可以乘以\(k\),另一边乘以\(k^2\),然后问你最终是否可以得到所给的两个数a ...

  7. 【LeetCode】82. Remove Duplicates from Sorted List II 解题报告(Python&C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地址:https://leetcode.com/problems/remove-du ...

  8. sql注入-整数型

    sql注入整数型   1.按照提示输入1,发现直接给出了SQL语句   2.使用order by判断字段数   首先使用order by 3 ,页面无回显,改为2之后页面显示正确.因此判断当前数据库当 ...

  9. 用C++创建Https客户端,用Mingw编译

  10. Autofac 依赖注入小知识

    Autofac 依赖注入小知识 控制反转/依赖注入 IOC/DI 依赖接口而不依赖于实现,是面向对象的六大设计原则(SOLID)之一.即依赖倒置原则(Dependence Inversion Prin ...