Inside The C++ Object Model 读书笔记(三)——持续、数据和函数的存储
添加时间:2013-6-13 点击量:
也是好久不写了,忙着写呈报、忙着这这那那的破事,其实很多时辰感觉作为一个法度猿甚至只是一个IT行业相干的人,可以或许安心肠、思路不被打乱地吃一本书或是写一段令自
己合意的代码是一件多么幸福的工作。直奔主题吧,C++的设计可谓是博大高深,有很多人因为如许那样的原因吐槽C++,然而在Inside The C++ Object Model一书中,作者
Stanley B.Lippman显现了C++的一些看似令人费解的设计的原因,信赖在懂得这些原因今后,某些对C++存有成见的人可以或许理性地对待C++的设计思惟。这篇就首要记下比来的
几点收成吧。
1.先来评论辩论第一个关于持续的小题目:
给定两个类,class Point2d,class Point3d,Point3d由Point2d持续而来,那么Point3d中到底有几许个成员变量,5个还是3个?若是是5个,怎么区分到底是从父类持续
的成员x、y还是自身的x、y?
1 class Point2d{
2 public:
3 int x;
4 int y;
5 };
6
7
8 class Point3d:public Point2d{
9 public:
10 int x;
11 int y;
12 int z;
13 };
很简单要确认这点,只用sizeof一下就行了,获得的答案是sizeof(Point3d)=20,如许就可以确认是5个成员变量了,进一步实例化一个Point3d对象:
Point3d ptr;
应用ptr.x的体式格式(哄骗对象直接接见),很明显是调用的Point3d类型的成员x、而非Point2d的x成员,这是合适设计思惟的(既然是特定独一类的成员,当然取出的应当是这
个类特有的成员)。那要怎么接见从父类持续的成员呢?
可以如许:Point2d pt = &ptr; //这也就是C++多态的定义、用一个基类的指针寻址出一个子类对象
pt->x;
此时接见的就是从父类持续的成员x。如许就可以得出一个结论:从父类持续的成员变量的名称和子类自身的成员变量名称容许反复,并且这是两个不合的成员。
2.虚拟持续
由持续的设计思惟,就又引出了别的一个题目。假设class A :public father; class B : public father; class C : public A, public B; 那么C的大小是几许?
遵守上方的设法,C++的在设计上,对于一个不含虚函数的类来说,似乎是子类的大小就是父类的大小再加上子类自身非静态成员变量的大小。没错,但这只实用于单一继
承,对于多重持续,景象就不一样了。试想若是C的大小便是A+B+C(特有menmbers),那么C中不就包含了两个father类的大小么?很显然这是一个不靠谱的设计体式格式,会引进额
外的存储空间,这不是大多半景象下所的。
于是C++在设计上供给了一种解决规划:虚拟持续。这使得派生类若是持续基类多次,也只有一份基类的拷贝在持续类对象中。即:
class father{...};
class A:public virtual father{...};
class B:public virtual father{...};
class C:public A, public B{...};
则C对象中只保存一个father类对象。一个class若是内含virtual base class则将被分别为两项目组:一个不变区域和一个共享区域。不变区的数据为非虚基类的数据,而共享区
就是虚基类数据。类中的虚函数表指针指向的虚函数表,正向偏移(向下)是寻址虚函数,负向偏移(向上)寻址的就是虚基类。还是以Point2d、Point3d类为例,Point3d由
Point2d持续而来,指针_vptr_Point3d指向虚函数表。
3.指向成员变量的指针
对于class Point3d的一个实例origin,&Point3d::z 和 &origin.z的成果是不合的,&Point3d::z该当为class Point3d内 member z的偏移量,而&origin.z 则为这个实例的member z 的地址。
然而在Microsoft Visual C++10.0下,下面几条语句履行成果却很独特。
printf(%p\n,&Point3d::x);
printf(%p\n,&Point3d::y);
printf(%p\n,&Point3d::z);
cout<<&Point3d::x<<endl;
cout<<&Point3d::y<<endl;
cout<<&Point3d::z<<endl;
前三条分别为:0, 4 ,8 (已验证,即为成员变量的偏移地址,在料想之中),书中写在BCB3下成果分别为5,9,D,我没有验证;后三条成果均为1很独特。公道的申明只能是VC++有过特别处理惩罚了。
好了就写到这里,持续进修吧~
我所有的自负皆来自我的自卑,所有的英雄气概都来自于我的软弱。嘴里振振有词是因为心里满是怀疑,深情是因为痛恨自己无情。这世界没有一件事情是虚空而生的,站在光里,背后就会有阴影,这深夜里一片寂静,是因为你还没有听见声音。—— 马良《坦白书》
也是好久不写了,忙着写呈报、忙着这这那那的破事,其实很多时辰感觉作为一个法度猿甚至只是一个IT行业相干的人,可以或许安心肠、思路不被打乱地吃一本书或是写一段令自
己合意的代码是一件多么幸福的工作。直奔主题吧,C++的设计可谓是博大高深,有很多人因为如许那样的原因吐槽C++,然而在Inside The C++ Object Model一书中,作者
Stanley B.Lippman显现了C++的一些看似令人费解的设计的原因,信赖在懂得这些原因今后,某些对C++存有成见的人可以或许理性地对待C++的设计思惟。这篇就首要记下比来的
几点收成吧。
1.先来评论辩论第一个关于持续的小题目:
给定两个类,class Point2d,class Point3d,Point3d由Point2d持续而来,那么Point3d中到底有几许个成员变量,5个还是3个?若是是5个,怎么区分到底是从父类持续
的成员x、y还是自身的x、y?
1 class Point2d{
2 public:
3 int x;
4 int y;
5 };
6
7
8 class Point3d:public Point2d{
9 public:
10 int x;
11 int y;
12 int z;
13 };
很简单要确认这点,只用sizeof一下就行了,获得的答案是sizeof(Point3d)=20,如许就可以确认是5个成员变量了,进一步实例化一个Point3d对象:
Point3d ptr;
应用ptr.x的体式格式(哄骗对象直接接见),很明显是调用的Point3d类型的成员x、而非Point2d的x成员,这是合适设计思惟的(既然是特定独一类的成员,当然取出的应当是这
个类特有的成员)。那要怎么接见从父类持续的成员呢?
可以如许:Point2d pt = &ptr; //这也就是C++多态的定义、用一个基类的指针寻址出一个子类对象
pt->x;
此时接见的就是从父类持续的成员x。如许就可以得出一个结论:从父类持续的成员变量的名称和子类自身的成员变量名称容许反复,并且这是两个不合的成员。
2.虚拟持续
由持续的设计思惟,就又引出了别的一个题目。假设class A :public father; class B : public father; class C : public A, public B; 那么C的大小是几许?
遵守上方的设法,C++的在设计上,对于一个不含虚函数的类来说,似乎是子类的大小就是父类的大小再加上子类自身非静态成员变量的大小。没错,但这只实用于单一继
承,对于多重持续,景象就不一样了。试想若是C的大小便是A+B+C(特有menmbers),那么C中不就包含了两个father类的大小么?很显然这是一个不靠谱的设计体式格式,会引进额
外的存储空间,这不是大多半景象下所的。
于是C++在设计上供给了一种解决规划:虚拟持续。这使得派生类若是持续基类多次,也只有一份基类的拷贝在持续类对象中。即:
class father{...};
class A:public virtual father{...};
class B:public virtual father{...};
class C:public A, public B{...};
则C对象中只保存一个father类对象。一个class若是内含virtual base class则将被分别为两项目组:一个不变区域和一个共享区域。不变区的数据为非虚基类的数据,而共享区
就是虚基类数据。类中的虚函数表指针指向的虚函数表,正向偏移(向下)是寻址虚函数,负向偏移(向上)寻址的就是虚基类。还是以Point2d、Point3d类为例,Point3d由
Point2d持续而来,指针_vptr_Point3d指向虚函数表。
3.指向成员变量的指针
对于class Point3d的一个实例origin,&Point3d::z 和 &origin.z的成果是不合的,&Point3d::z该当为class Point3d内 member z的偏移量,而&origin.z 则为这个实例的member z 的地址。
然而在Microsoft Visual C++10.0下,下面几条语句履行成果却很独特。
printf(%p\n,&Point3d::x);
printf(%p\n,&Point3d::y);
printf(%p\n,&Point3d::z);
cout<<&Point3d::x<<endl;
cout<<&Point3d::y<<endl;
cout<<&Point3d::z<<endl;
前三条分别为:0, 4 ,8 (已验证,即为成员变量的偏移地址,在料想之中),书中写在BCB3下成果分别为5,9,D,我没有验证;后三条成果均为1很独特。公道的申明只能是VC++有过特别处理惩罚了。
好了就写到这里,持续进修吧~
我所有的自负皆来自我的自卑,所有的英雄气概都来自于我的软弱。嘴里振振有词是因为心里满是怀疑,深情是因为痛恨自己无情。这世界没有一件事情是虚空而生的,站在光里,背后就会有阴影,这深夜里一片寂静,是因为你还没有听见声音。—— 马良《坦白书》