一、Data Member 的绑定(The binding of Data Member)

 extern float x;

 class Point3d
{
public:
Point3d( float, float, float);
float X() const { return x; }
void X( float new_x ) const { x = new_x; }
// ...
private:
float x,y,z;
};

  请问 Point3d::X()传回哪一个x?是class 内部那个还是外部(extern )的那个?大家肯定都会说传回 class 内部的那个,这个回答是真正确的。但是在早期的c++中可不一定哦,早期的C++的取用操作会指向 global x object,这出乎大家的意料。那么早期是如何预防这种错误呢?有以下两种办法:

  (1). 将所有的data member 定义到 class 声明的起始处,以确保正确的绑定,如下:

 extern float x;

 class Point3d
{
float x,y,z;
public:
Point3d( float, float, float);
float X() const { return x; }
void X( float new_x ) const { x = new_x; }
// ...
};

  (2). 把所有的 inline function,不管大小都放在 class 声明之外,即将 member functions 放在class 类里面声明,放到 class 外面进行定义,这里就不举例!

  而今天的代码完全不用像上面那样需要进行考虑,因为现在的编译器对 member functions 的分析会直到整个 class 的声明都出现了才开始。因此在一个 inline member function 函数体内的一个 data member 绑定操作,会在整个 class 声明完成之后发生。但是,对于 member function 的 argument list 并不为真哦!请看下面这个例子:

 #include <iostream>

 using namespace std;

 typedef int length;

 class A
{
private:
typedef float length;
length num;
public:
void setNum( length _num )
{
num = _num;
} }; int main()
{
system("pause");
}

  这个代码并没有运行结果,可以通过编译!但是编译器会给出一个提醒:

    警告 1 warning C4244: “=”: 从“length”转换到“A::length”,可能丢失数据 

  这是为什么呢?因为你的成员变量 num 定义的是 float 型,而你的 setNum() 的参数 _num 是 int 型!咋进行赋值时会进行强制转化,这样编译器会给出如上的警告。由此可说明:对于 member function 的 argument list 并不是取用 class 的 typedef 的 length 而是 全局变量 length,所以在写这样的代码要小心了哦。如果你想要 argment list 的也是用 clas 内的 length ,就把内嵌的 typedef 定义放到他要被用到的地方的前面即可咯!

二、Data Member 的布局(Data Member Layout)

  nonstatic data members 在 class object 中排列的顺序将和其被声明的顺序一致,任何的static data members都不会被放到对象布局之中。而是存放在程序的 数据段(data segment)而与个别的 class 无关。C++的标准是要求在同一个访问级别(也就是 public、private、protected)中,members 的排列只需符合“较晚出现的 members 在 class object 中具有较高地址“,并没要求他们是连续排列的。那么什么东西会被介于被声明的 members 之间呢?

  a. members 的边界调整(alignment) 可能就需要填补一些 bytes. 这样就会隔开两个相连的member啦。

  b. 编译器可能会合成一些内部使用的 data members 以支持整个对象模型。vptr 就是这一类东西,虽然没规定它放在哪个位置。但是一般 vptr 会被放在 class object 的声明的 members 的最后,不过也有编译器会把 vptr 放在 class object 的最前端---不太可能会插到 members 之间啦。

三、Data Member 的存取

  (1). static data members

  我们之前的博文说道不管是没有 class object 、有一个class object 或者 n 个object 这个类的 static data members 都已经存在于程序的 data segment 中了(前提是你得定义了这些 static data members 哈),并且只有一份!大家知道 static data members 可以通过class 的 "::"访问,也可以通过 class object 的"."访问,其实别看他和其他nonstatic 成员一样 通过"."访问,其实它根本不像 nonstatic data members 一样存储在 class object 中啦。这样只是为了方便操作,其实通过"::"访问才是原汁原味的!!!

  既然 static data member 都是一份实体存在 程序的 datasegment 中,那么如果一个程序中的两个类有了同样名字的 static data member 就会导致名称冲突,怎么办?不要怕,编译器会对每个 static data member 进行编码(这种手法叫做:name-mangling),以获得一个独一无二的程序识别代码。当然,每个编译器的 name-mangling 做法都不一样,但无论怎么样他们要做的莫非一下两点:

  a. 一种算法,推导出独一无二的名称。

  b. 万一预编译系统(或编译工具)必须和使用者交谈,那些独一无二的名称就可以轻易的被推到回到原来的名称。(比如报错,提示说你这个 static data member 哪里错误,在给出名字的时候当然是用程序员的命的名称而不是编码后的名称!)

  (2). nonstatic data members

  nonstatic data members 的大小被存放在一个 class object中,并通过 "." 访问。看下面这个例子:

 #include <iostream>

 using namespace std;

 typedef int length;

 class A
{
public:
virtual void foo(){};
int num1,num2,num3;
}; int main()
{
A a;
A *pa = &a ;
printf(" &A::num2 = %p\n",&A::num2);
cout << &a << endl;
cout << &a.num2 << endl;
cout << &(pa->num2) << endl;
return ;
}

  以下是输出结果:

  

  我来解释一下:第一行是data member num2 在class 中的偏移量。第二行是 class A 在内存中的真实地址,第三行和第四行都是num2在内存中的真实地址。

  大家发现图中的:0012FF40( num2 的地址 ) = 0012FF38( a 的首地址) + 00000008( num2 在 class A 中的偏移量); 没?

  所以你不管是通过 class object 的 "." 访问或者通过class pointer 的 "->" 访问nonstatic data member,编译器都是通过:class object 的首地址 + 该 data member 在class 中的 offset (偏移量)。注意:在通过 class pointer ( 类指针)访问 nonstatic data member的时候,如果该 nonstatic data member 是 virtual base classs 的 data member ,那情况会有所不同哦!不过不用担心---虚继承总是不同于其他情况(具体请看 Data 语义学(2) 中对各种情况的介绍),我们多多注意就行了!

Data 语义学(1)的更多相关文章

  1. Data 语义学(2)

    四."继承"与 Data Member (1). 只有继承没有多态 先来看个例子 #include <iostream> using namespace std; cl ...

  2. C++对象模型(五):The Semantics of Data Data语义学

    本文是<Inside the C++ Object Model>第三章的读书笔记.主要讨论C++ data member的内存布局.这里的data member 包含了class有虚函数时 ...

  3. 【C++对象模型】第三章 Data语义学

    1. Data Member 的布局 同一个Access Section(private, public等)中,data member的顺序按照声明顺序排列,但是没有规定需要连续排序.同时编译器可能会 ...

  4. 【深入探索c++对象模型】data语义学二

    单一继承中,base class 和derived class的对象都是从相同的地址开始,其间差异只在于derived class比较大,用以容纳自己的nonstatic members. 若vptr ...

  5. 【深度探索C++对象模型】data语义学

    class X{}; class Y :public virtual X{}; class Z :public virtual X{}; class A :public Y, public Z{}; ...

  6. 深入探索C++对象模型(三)

    Data 语义学 一个class的data members,一般而言,可以表现这个class在程序执行时的某种状态.Nonstatic data members放置的是"个别的class o ...

  7. Linux Debugging(四): 使用GDB来理解C++ 对象的内存布局(多重继承,虚继承)

    前一段时间再次拜读<Inside the C++ Object Model> 深入探索C++对象模型,有了进一步的理解,因此我也写了四篇博文算是读书笔记: Program Transfor ...

  8. CYQ.Data、ASP.NET Aries 百家企业使用名单

    如果您或您所在的公司正在使用此框架,请联系左侧的扣扣,告知我信息,我将为您添加链接: 以下内容为已反馈的用户,(收集始于:2016-08-08),仅展示99家: 序号 企业名称 企业网址 备注 1 山 ...

  9. 终于等到你:CYQ.Data V5系列 (ORM数据层)最新版本开源了

    前言: 不要问我框架为什么从收费授权转到免费开源,人生没有那么多为什么,这些年我开源的东西并不少,虽然这个是最核心的,看淡了就也没什么了. 群里的网友:太平说: 记得一年前你开源另一个项目的时候我就说 ...

随机推荐

  1. linux上传下载软件

    如何实现windows和linux之间的文件传输 (原文地址:http://hi.baidu.com/ying5420/item/439dee93f0f7fd1a934f41e2) 如果想从windo ...

  2. Linux系统下查看USB设备名及使用USB设备

    1.系统插入USB设备后,从控制台界面有如下提示: 从控制台信息可以看出插入的USB设备名. 从上图可以看出,插入的USB设备为sde4. 但是,如果是CRT工具远程连接过去,可以使用下面的命令来查看 ...

  3. list-style无颜色问题解决,list-style-type无颜色解决

    list-style无颜色问题解决,list-style-type无颜色解决 >>>>>>>>>>>>>>>& ...

  4. sql 减去分钟

    SQL SERVER:SELECT DATEADD( minute,-10,GETDATE()) ORACLE:SELECT to_char(sysdate -interval '10' minute ...

  5. SDK Manager.exe 无法启动,一闪而过的解决办法

    删掉 C:\Windows\system32\ 下的 java.exe.javaw.exe.javaws.exe 即可解决.(转载)

  6. How to customize authentication to my own set of tables in asp.net web api 2?

    ssuming your table is called AppUser, convert your own AppUser domain object to IUser(using Microsof ...

  7. CI 笔记3 (easyui 的layout布局,最小化layout原型)

    在做easyui的layout的布局时,最小化一个原型,分2步,一个是div的父标签,一个是body做父标签,全屏的. 步骤分别为: 在设置的5个区中,div的最后一个,必须是data-options ...

  8. oracle中所有关于时间日期的问题总结

    select current_date as 当前会话时间,sysdate as 系统时间, systimestamp as 系统详细时间 from dual;

  9. angular template浅析

    在我们浏览的页面中有大的网站,也有中小型网站,类型不同其中的页面也就不同,但是纵观大部分的网页是否有什么相同的地方呢?如果浏览的是一般的门户网站或者是什么小型的页面的话这种感觉就不是很明显,但是如果关 ...

  10. javascript基础学习(八)

    javascript之日期对象 学习要点: 日期对象 将日期对象转换为字符串 将日期对象中的日期和时间转换为字符串 日期对象中的日期 日期对象中的时间 设置日期对象中的日期 设置日期对象中的时间 与毫 ...