读书笔记 《深度探索c++对象模型》 (4)
2010年07月04日
第五章:构造,解构,拷贝语意学
5.2 继承体系下的对象构造
a) 虚拟继承
如同下面的继承情况:#include #include using namespace std; class Point { public: Point() { printf("Point : constructor\n"); } virtual ~Point() { printf("Point : destructor\n"); } protected: float _x, _y; }; class Point3d : public virtual Point { public: Point3d() { printf("Point3d : constructor\n"); } ~Point3d() { printf("Point3d : destructor\n"); } protected: float _z; }; class Vertex : public virtual Point { public: Vertex() { printf("Vertex : constructor\n"); } ~Vertex() { printf("Vertex : destructor\n"); } protected: float _w; }; class Vertex3d : public Point3d, public Vertex { public: Vertex3d() { printf("Vertex3d : constructor\n"); } ~Vertex3d() { printf("Vertex3d : destructor\n"); } protected: float _u; }; int main () { Vertex3d *pV3d = new Vertex3d; delete pV3d; pV3d = NULL; return 0; } 在这种情况下,Vertex3d压制了它的两个父类对Point constructor的调用,这个调用工作由Vertext3d本身来完成。所以输出为:
b) vptr初始化语意学
接着上面的例子:#include #include using namespace std; class Point { public: Point() { self(); } virtual ~Point() { printf("Point : destructor\n"); } virtual void self() { printf("Point : self\n"); } protected: float _x; }; class Point3d : public virtual Point { public: Point3d() { self(); } ~Point3d() { printf("Point3d : destructor\n"); } void self() { printf("Point3d : self\n"); } protected: //float _z; }; class Vertex : public virtual Point { public: Vertex() { self(); } ~Vertex() { printf("Vertex : destructor\n"); } void self() { printf("Vertex : self\n"); } protected: //float _w; }; class Vertex3d : public Point3d, public Vertex { public: Vertex3d() { self(); } ~Vertex3d() { printf("Vertex3d : destructor\n"); } void self() { printf("Vertex3d : self\n"); } protected: //float _u; }; int main () { Vertex3d *pV3d = new Vertex3d; delete pV3d; pV3d = NULL; return 0; } 输出为:
这说明,虽然new出来的是一个Vertex3d对象,但是在每个constructor中调用的self,既不是基类的self,也不是Vertex3d的self,而都会被决议为是当前class的self。这个和vptr的初始化有关,因为vptr的初始化,是在base class constructor调用操作之后,在当前constructor执行或者当前constructor的member initialization list初始化之前。
一个constructor的执行算法如下:
1. 执行所有virtual base class以及上一层base class的constructor。
2. 初始化vptr。
3. member initialization list执行。
4. 执行constructor的代码。
5.3 对象复制语意学
如果我们明确的想要拒绝把一个class object指定给另一个class object,那么我们可以将copy assignment operator指定为private,并且不提供它的定义。
一个class对于默认的copy assignment operator,在以下四种情况下不会出现bitwise copy语意:
1. 当class内带一个class object,其class带有一个copy assignment operator;
2. 当一个class的base class有一个copy assignment operator时;
3. 当一个class声明了任何的virtual functions时;(因此不必担心vptr是否会被copy)
4. 当class继承自一个virtual base class时;
5.5 解构语意学
一个destructor的执行算法与constructor类似,但顺序相反:
1. destructor函数本身首先被执行;
2. 如果class member带有destructor,那么它们会以声明顺序的相反顺序被调用;
3. 如果一个object带有一个vptr,那么vptr被重新设定,指向适当的base class的virtual table;
4. 如果有直接的nonvirtual base class拥有destructor,那么它们会以声明顺序的相反顺序执行;
5. 如果有任何的virtual base class拥有destructor,而当前讨论的这个class是最尾端的class(保证virtua base class的destructor只被调用一次),那么它们会以其原来的构造顺序的相反顺序执行。
附:#include #include using namespace std; class Point { public: Point() { } virtual ~Point() { } protected: float _x; }; class Point3d : public virtual Point { public: Point3d() { } ~Point3d() { } public: //int _z; }; class Vertex : public virtual Point { public: Vertex() { } ~Vertex() { } protected: //float _w; }; class Vertex3d : public Point3d, public Vertex { public: Vertex3d() { } ~Vertex3d() { } protected: //float _u; }; int main () { Vertex3d *pV3d = new Vertex3d; printf("%d\n", sizeof(Point)); printf("%d\n", sizeof(Point3d)); printf("%d\n", sizeof(Vertex)); printf("%d\n", sizeof(Vertex3d)); delete pV3d; pV3d = NULL; return 0; }
输出的结果可以分析为:
class Point有一个4bytes的float member和一个4bytes的vptr,该vptr中含有virtual destructor的地址;
class Point3d有一个4bytes的float member和两个4bytes的vptr,其中一个是继承下来的,另外一个含有virtua base class的offset;
class Vertex同上;
class Vertex3d有一个8bytes的Point,还分别有两个4bytes的Point3d和Vertex;
但是,如果去掉Point中的member:#include #include using namespace std; class Point { public: Point() { } virtual ~Point() { } protected: //float _x; //去掉 }; class Point3d : public virtual Point { public: Point3d() { } ~Point3d() { } public: //int _z; }; class Vertex : public virtual Point { public: Vertex() { } ~Vertex() { } protected: //float _w; }; class Vertex3d : public Point3d, public Vertex { public: Vertex3d() { } ~Vertex3d() { } protected: //float _u; }; int main () { Vertex3d *pV3d = new Vertex3d; printf("%d\n", sizeof(Point)); printf("%d\n", sizeof(Point3d)); printf("%d\n", sizeof(Vertex)); printf("%d\n", sizeof(Vertex3d)); delete pV3d; pV3d = NULL; return 0; } 输出:
我的理解是:
class Point有一个4bytes的vptr,该vptr中含有virtual destructor的地址;
class Point3d有一个4bytes的float member,由于virtual base class没有member,所以就没有一个vtable来存放virtual base class的offset,而Point3d本身也没有virtual function;
class Vertex同上;
class Vertex3d包含了一个Point3d和一个Vertex;
以上测试编译环境为GCC。
发表评论
-
pv3d视频教程
2012-01-20 01:47 820pv3d视频教程 2010年08月06日 原址: 内容: ... -
Papervision3D Essentials 要点整理
2012-01-20 01:47 571Papervision3D Essentials 要点 ... -
Android Bitmap和Canvas
2012-01-20 01:47 725Android Bitmap和Canvas 2010年09月 ... -
VxWorks下编程的几个误区
2012-01-20 01:47 775VxWorks下编程的几个误区 ... -
小学生作文批改评语
2012-01-19 09:34 572小学生作文批改评语 2011年09月05日 作文开头: ... -
小学作文评语原则及思考
2012-01-19 09:34 543小学作文评语原则及思 ... -
服务器控件的三个ID
2012-01-19 09:34 775服务器控件的三个ID 2011年05月22日 在ASP. ... -
学习左向相平得体会
2012-01-19 09:34 573学习左向相平得体会 20 ... -
2011-12-22
2012-01-19 09:34 4952011-12-22 2011年12月22日 ... -
我的文件17/1
2012-01-17 02:09 510我的文件17/1 2010年07月26日 Protel技 ... -
2011年计算机三级考试PC技术知识要点(32)
2012-01-17 02:09 6502011年计算机三级考试PC ... -
FLTK简介
2012-01-17 02:09 551FLTK简介 2011年11月22日 ... -
J2SE简介与J2EE、J2ME的比较
2012-01-17 02:09 668J2SE简介与J2EE、J2ME的比较 2010年06月15 ... -
ApplicationDomain.currentDomain的细节
2012-01-15 21:41 614ApplicationDomain.currentDomain ... -
【顶】FLASH教程――目录
2012-01-15 21:41 618【顶】FLASH教程――目录 2009年09月15日 追 ... -
AS3容器的实现原理
2012-01-15 21:41 567AS3容器的实现原理 2010年07月09日 所谓 ... -
2009 - 2010 Flex 工作笔记
2012-01-15 21:40 6982009 - 2010 Flex 工作笔记 ... -
【顶】flash教程――目录
2012-01-15 21:40 616【顶】flash教程――目录 2009年09月15日 F ...
相关推荐
深度探索C++对象模型的阅读笔记,可以看看别人是怎么学习C++的
深度探索C++对象模型读书笔记
深度探索C++对象模型(笔记)
NULL 博文链接:https://dsqiu.iteye.com/blog/1669614
总结笔记,关于侯捷翻译的《深入探索c++对象模型》的笔记 作者Lippman参与设计了全世界第一套C++编译程序cfront,这本书就是一位伟大的C++编译程序设计者向你阐述他如何处理各种explicit(明确出现于C++程序代码中)...
本人自己的学习《深度探索C++对象模型》的笔记,但实际上内容为本人自己的实验结果,与原书无关,绝对原创。
引入继承后的对象模型成本:如果是普通的继承,父对象被直接包含在子对象里面,这样对父对象的存取也是直接进行的,没有额外的成本;如果是虚拟继承,则父对象会由一个指针
收集的关于C++的学习资料.主要是深度解析C++对象模型的读书笔记。
深入C++对象模型的读书笔记 主要是将C++对象模型的内容做了提炼,关注更常用的一些知识。 内容基本依照原文,未作改动。实验中,也感觉此书与当下C++编译器脱节严重,有些东西不是太适用了,但仍不失为一份好的参考...
C++Primer中文第三版(C++从入门到精通)第一章的读书笔记,主要是C++程序、预处理器指示符、iostream库等的基础知识点读书笔记。
深度探索C++对象模型(6)这是这个系列笔记的第7篇了,我们还在和构造函数打交道,以前写程序时怎么根本没有考虑过构造函数的事情呢?原来编译器为我们做了这么多的事情,我们都不知道.,要想完全搞明白,看来还需要一段...
effective c++读书笔记和总结 effective c++读书笔记和总结
C++读书笔记
C++Primer摘记,还不错.是第四版的
effective C++读书笔记,effective C++读书笔记,effective C++读书笔记
《C++.GUI.Programming.with.Qt.4》读书笔记
C++学习笔记C++学习笔记C++学习笔记C++学习笔记C++学习笔记
effective C++ 很好 很不错 最好的C++进阶资料
USB读书笔记 USB读书笔记 USB读书笔记 USB读书笔记