在C++中对象的内存布局与类成员声明的顺序一致,静态成员放在数据区(Data Section)而非对象内存中,若多个类静态成员名称相同,C++则按照name mangling技术进行重命名保证名称的唯一性。若类之间发生了继承关系(无虚拟指针无虚继承)时,按照基类、子类成员顺序排列,另在C++对象复制中,有一个规则:基类子对象(base class object)在派生类(derived class member)中成员的原样性

测试代码如下:

#include <iostream>
#include <iomanip>
#include <cassert> using namespace std; class Concrete1 {
public:
void foo(void) {
cout << "concrete1:" << bit1 << endl;
}
Concrete1():val(1),bit1('a') {
}
public:
int val;
char bit1;
}; class Concrete2:public Concrete1 {
public:
char bit2;
public:
void foo(void) {
cout << "concreate2" << bit2 << endl;
} Concrete2():bit2('b'),Concrete1() {
}
}; class Concrete3: public Concrete2 {
public:
void foo(void) {
cout << "concrete3:" << bit3 << endl;
} Concrete3():bit3('c'),Concrete2() {
} public:
char bit3;
}; template <class data_type1,class data_type2>
const char *access_order(data_type1 *mem1,data_type2 *mem2)
{
unsigned long p1,p2; p1 = (unsigned long)(mem1);
p2 = (unsigned long)(mem2); assert(p1 != p2); return p1 < p2
? "member 1 occurs first"
:"member 2 occurs first";
} int main(int argc, char *argv[])
{
Concrete2 c2,*pc2;
Concrete1 c1,*pc1_1,*pc1_2;
Concrete3 c3; pc2 = &c3;
pc1_1 = pc2;
pc1_2 = &c1;
char *b; //access_order(&Concrete1::bit1,&Concrete1::bit);
cout << "address val and bit1:" << access_order(&c1.val,&c1.bit1) << endl;
cout << "Concrete3:" << sizeof(Concrete3) << endl; //b = *(char *)((char *)(&(pc1_2->bit1)) + 1);
b = &(pc1_2->bit1); cout << "Before address:" << hex << static_cast<void *>(b) << ",b:" << *b << endl;
b++;
cout << "After address:" << hex << static_cast<void *>(b) << endl;
cout << "b:" << *b << "b+1:" << *(b+1)<< endl;
cout << "Memberwise copy." << endl;
*pc1_2 = *pc1_1;
//b = *(char *)((char *)(&(pc1_2->bit1)) + 1);
b = &(pc1_2->bit1); cout << "Before address:" << hex << static_cast<void *>(b) << ",b:" << *b << endl;
b++;
cout << "After address:" << hex << static_cast<void *>(b) << endl;
cout << "b:" << *b << "b+1:" << *(b+1)<< endl;
pc1_2->foo(); return 0;
}

g++ 运行情况如下:

f:\code\C++\study>concrete
concrete
address val and bit1:member 1 occurs first
Concrete1:8//三个类大小均为8字节
Concrete2:8
Concrete3:8
Before address:0x22ff34,b:a
After address:0x22ff35
b: b+1:"
Memberwise copy. //复制前后Concrete1对象填充字节内容未变化
Before address:0x22ff34,b:a
After address:0x22ff35
b: b+1:"
concrete1:a

vs2010运行如下:

testlayout
address val and bit1:member 1 occurs first
Concrete1:8//三个类大小均不同,采用了对齐方式处理
Concrete2:12
Concrete3:16
Before address:0012FF40,b:a
After address:0012FF41
b:蘠+1:
Memberwise copy. //复制前后Concrete1对象填充字节内容未变化
Before address:0012FF40,b:a
After address:0012FF41
b:蘠+1:
concrete1:a

C++类成员布局的更多相关文章

  1. C++类内存布局图(成员函数和成员变量分开讨论)

    一.成员函数 成员函数可以被看作是类作用域的全局函数,不在对象分配的空间里,只有虚函数才会在类对象里有一个指针,存放虚函数的地址等相关信息. 成员函数的地址,编译期就已确定,并静态绑定或动态的绑定在对 ...

  2. Objective-C类成员变量深度剖析

    目录 Non Fragile ivars 为什么Non Fragile ivars很关键 如何寻址类成员变量 真正的“如何寻址类成员变量” Non Fragile ivars布局调整 为什么Objec ...

  3. C#定义类成员

    1.成员定义 public--成员可以由任何代码访问. private--成员只能由类中的代码访问(如果没有使用任何关键字,就默认使用这个关键字). internal--成员只能由定义它的程序集(项目 ...

  4. 理解ATL中的一些汇编代码(通过Thunk技术来调用类成员函数)

    我们知道ATL(活动模板库)是一套很小巧高效的COM开发库,它本身的核心文件其实没几个,COM相关的(主要是atlbase.h, atlcom.h),另外还有一个窗口相关的(atlwin.h), 所以 ...

  5. c++空指针调用类成员函数

    最近在看C++动态绑定问题时(理解静态绑定时)发现的问题:能用空指针调用类的成员函数(gcc,vs2013下都可以). 例子: class animal { public: void sleep(){ ...

  6. 深入理解类成员函数的调用规则(理解成员函数的内存为什么不会反映在sizeof运算符上、类的静态绑定与动态绑定、虚函数表)

    本文转载自:http://blog.51cto.com/9291927/2148695 总结: 一.成员函数的内存为什么不会反映在sizeof运算符上?             成员函数可以被看作是类 ...

  7. Objective-C类成员变量深度剖析--oc对象内存模型

    目录 Non Fragile ivars 为什么Non Fragile ivars很关键 如何寻址类成员变量 真正的“如何寻址类成员变量” Non Fragile ivars布局调整 为什么Objec ...

  8. OC基础--结构体 枚举做类成员属性

    结构体  枚举作类的成员属性: 定义一个学生类 性别 -- 枚举 生日 入学日期  毕业日期  --  结构体 代码示例: 声明文件 Student.h: #import <Foundation ...

  9. 重载运算符:类成员函数or友元函数

    类成员函数: bool operator ==(const point &a)const { return x==a.x; } 友元函数: friend bool operator ==(co ...

随机推荐

  1. c语言基础表达式, 关系运算符, 逻辑运算符, 位运算符, 数据的取值范围, 分支结构(if...else, switch...case)

    1.表达式: 表达式的判断是有无结果(值), 最简单的表达式是一个常量或变量, 如:12, a, 3 + 1, a + b, a + 5 都是表达式 2.BOOL(布尔)数据类型: c语言中除了基本数 ...

  2. Emmet 使用说明。

    Emmet for Sublime Text Official Emmet plugin for Sublime Text. How to install Available actions Exte ...

  3. HttpServletResponse常用的方法

    所有Servlet响应都实现ServletResponse接口.ServletResponse接口主要有以下方法: (1)从Servlet中可以通过getWriter方法取得PrintWriter对象 ...

  4. Anagrams

    这题Leetcode上面的描述不清楚.怎么也得举两个例子吧,不然谁懂? 题目的意思是,给定一些字符串,比如["abc","cba","bac" ...

  5. 编译内核实现iptables防火墙layer7应用层过滤 (三)

    在前面的两篇文章中我们主要讲解了Linux防火墙iptables的原理及配置规则,想博友们也都知道iptables防火墙是工作在网络层,针对TCP/IP数据包实施过滤和限制,属于典型的包过滤防火墙.以 ...

  6. Jacoco入门

    Jacoco介绍 转自:wangmuming 的博客 Jacoco是一个开源的覆盖率工具.Jacoco可以嵌入到Ant .Maven中,并提供了EclEmma Eclipse插件,也可以使用JavaA ...

  7. 扩展django的User的部分方法

    这做项目时发现django自带的User中的字段不够用,默认的auth_user表总共只有11个字段,如果需要更多的字段该怎么办,在网上搜了一下,有这么几种方法. 1. 直接修改django 源码,修 ...

  8. unslider.js 实现移动web轮播

    unslider.js可以实现轮播,但是在移动端还需要另两个插件. jquery.event.move和jQuery.event.swipe : 下面就是简单的实例: <!doctype htm ...

  9. 记录Js

    1.对于js,没有系统的学习.有要经常的用到,每次都是百度查找,为了以后能查询. (1). $(function () { $('.restbtn').on("click", fu ...

  10. Ubuntu Git 入门

    参考自 码农生涯 中大熊猫 hustpzb的专栏 1 在github创建账号--创建repository 2 创建后网页会出现提示,指导如何使用 3 安装git sudo apt-get instal ...