
深度探索c++对象模型
文章平均质量分 51
发如雪-ty
一个工作多年的程序员,一直从事C++开发方面的工作,曾有幸在安防行业深耕4年,并有幸在工业检测行业工作至今已有4年,主要负责系统软件的设计与开发,个人编程的信仰:不要盲目学习酷炫的东西,最重要的依然是内功。
展开
-
对象切割时虚指针VPTR探索
对象切割,虚指针探索原创 2023-10-14 00:06:42 · 189 阅读 · 0 评论 -
深度探索c++对象模型-31-RTTI与存储位置简介
RTTI原创 2023-04-02 13:37:21 · 426 阅读 · 0 评论 -
深度探索c++对象模型-30-数据成员绑定时机
数据成员绑定时机原创 2023-03-26 14:55:33 · 112 阅读 · 0 评论 -
深度探索c++对象模型-29-虚函数表的创建时机
虚函数表创建时机原创 2023-03-26 14:08:37 · 264 阅读 · 0 评论 -
深度探索c++对象模型-28-成员函数参数类型的确定时机
有如下类:typedef string Mytype;class A{public: int a; A() { cout << "A()\n"; } void myfunc(Mytype tmpvalue) { value = tmpvalue; }private: typedef int Mytype; Mytype value;};编译一下就会报错,如下:现在做个修改:typedef string Mytype;class A{原创 2021-08-08 13:38:43 · 116 阅读 · 0 评论 -
深度探索c++对象模型-27-继承体系下的对象构造
一、对象的构造顺序class A{public: A() { printf("A::A()执行了,this=%p\n", this); } virtual ~A() { }};class B :public A{public: B() { printf("B::B()执行了,this=%p\n", this); } virtual ~B() { }};class C :public B{public: C() { printf("C:原创 2021-08-06 23:55:34 · 157 阅读 · 0 评论 -
深度探索c++对象模型-26-Inline函数及其扩展
有如下代码:int get(int a, int b){ return a + b;}void main(){ int c = get(10, 20); system("pause");}启用调用模式,看到如下情况:然后修改为inline,函数如下:inline int get(int a, int b){ return a + b;}从结果可以看出内联成功了,少了压栈的操作。内联函数(inline function与一般的函数不同,它不是在调用时发生控制转原创 2021-08-06 00:07:23 · 211 阅读 · 0 评论 -
深度探索c++对象模型-25-指向成员函数的指针和vcall
一、指向成员函数的指针class A{public: void myfunc1(int nTempValue) { cout << "nTempValue = " << nTempValue << endl; } void myfunc2(int nTempValue2) { cout << "nTempValue2 = " << nTempValue2 << endl; }};void func原创 2021-08-05 22:45:43 · 195 阅读 · 0 评论 -
深度探索c++对象模型-24-函数调用、继承关系性能说
一、函数调用中编译器的循环代码优化1.1debug模式看如下代码:__int64 mytest(int mv){ __int64 icount = 0; for (int i = 1; i < 1000000; i++) { icount += 1; } return icount;}void main(){ clock_t start, end; __int64 mycount = 1; start = clock(); for (int i = 0; i原创 2021-08-04 00:19:39 · 201 阅读 · 0 评论 -
深度探索c++对象模型-23-多继承第二基类虚函数支持、虚继承带虚函数
一、多重继承第二基类对虚函数支持的影响(this指针调整作用)子类继承了几个父类,子类就有几个虚函数表this指针调整的目的就是让对象指针正确的指向对象的首地址,从而能正确的调用对象的成员函数或者说正确确定数据成员的存储位置。看如下代码:class Base{public: Base() { printf("Base::this = %p\n",this); } virtual void f() { cout << "Base:f()" << endl原创 2021-08-01 17:21:07 · 263 阅读 · 1 评论 -
深度探索c++对象模型-22-多继承虚函数深释、第二基类、虚析构必加
一、多继承下的虚函数class Base{public: Base() { printf("Base::this = %p\n",this); } virtual void f() { cout << "Base:f()" << endl; } virtual void g() { cout << "Base:g()" << endl; } virtual void h() { cout << "原创 2021-08-01 12:02:33 · 233 阅读 · 0 评论 -
深度探索c++对象模型-21-单继承虚函数趣味性测试和回顾
一、单继承下的虚函数class Base{public: virtual void f() { cout << "Base:f()" << endl; } virtual void g() { cout << "Base:g()" << endl; } virtual void h() { cout << "Base:h()" << endl; }};class Derive :public原创 2021-07-31 00:00:32 · 177 阅读 · 1 评论 -
深度探索c++对象模型-20-静东态、绑定、坑点、多态体现深谈
有如下代码:class Base{public: };class Derive :public Base{public: };class Derive2:public Base{public:};一、静态类型和动态类型静态类型:对象定义时的类型,编译期间就确定好了。void main(){ //静态类型: Base base;//base的静态类型是Base Derive derive;//derive的静态类型是Base Base *pbase;//p原创 2021-07-29 23:20:26 · 168 阅读 · 1 评论 -
深度探索c++对象模型-19- 虚成员函数、静态成员函数调用方式
一、虚成员函数的调用方式但这种情况是明确不使用多态。虚函数和普通成员函数一样,在内存中也有一个固定的内存地址。也是在编译的时候确定好的。原创 2021-07-28 22:31:04 · 427 阅读 · 0 评论 -
深度探索c++对象模型-18-普通成员函数调用方式
原创 2021-07-27 23:20:56 · 130 阅读 · 0 评论 -
深度探索c++对象模型-17-成员变量地址、偏移、指针等重申
一、对象成员变量内存地址及其指针结果:二、成员变量的编译值及其指针注意成员变量指针里面保存的实际上是个偏移值(不是实际的内存地址)三、没有指向任何数据成员变量的指针成员变量指针可以当做参数使用调用下面是有意思的地方:结果竟然是-1,如下:...原创 2021-07-25 22:53:50 · 315 阅读 · 0 评论 -
深度探索c++对象模型-16-两层结构时虚基类表内容分析
一、虚基类表内容之5-8字节内容分析虚基类表一般是编译的时候编译器就生成了,一般是8个字节,4个字节为一个单位。每多一个虚基类会多 四个字节。本节只讨论一个虚基类的情况。编译器因为有虚基类,会给A1,A2类增加默认的构造函数,并且这个默认构造函数里,会别编译器增加进去代码,给vbptr虚基类表指针赋值。“虚基类表指针”成员变量的首地址 + 这个偏移量 就等于虚基类对象的首地址。跳过这个偏移值,我们就能够访问到虚基类对象。重点:虚基类表中存放的是虚基类成员的偏移值二、继续观察各种形色的继承注意下面原创 2021-07-25 21:22:49 · 322 阅读 · 0 评论 -
深度探索c++对象模型-15-虚基类问题的提出和初探
一、虚基类(虚继承、虚派生)问题的提出如上这个继承关系(也就是传统继承)会造成空间问题,效率问题,二义性问题。看如下代码:class Grand{public: int m_grand;};class A1 :public Grand{public:};class A2 :public Grand{public:};class C1 :public A1, public A2{};void main(){ cout << sizeof(Gra原创 2021-07-25 17:39:50 · 213 阅读 · 2 评论 -
深度探索c++对象模型-14-多重继承数据布局与this调整深谈
一、单一继承数据成员布局this指针偏移知识补充上一节我们知道,子类没有虚函数,而子类有虚函数的单一继承中,布局如下:因为vptr的地址在开始,所以当访问父类的m_bi的时候,将会进行this指针调整,也就是调整4个字节。下面看代码改造,看看实际的this指针调整class father{public: int m_fi; father() { printf("father:father()的this指针调整:%p\n", this); }};class MYCLASS:p原创 2021-07-24 14:26:14 · 421 阅读 · 3 评论 -
深度探索c++对象模型-13-单类单继承下的数据成员布局
一、单个类带虚函数的数据成员布局class MYCLASS{public: int m_i; int m_j; virtual void myvirfunc() { } MYCLASS() { int abc = 1; } ~MYCLASS() { int abc = 1; }};void main(){ cout << sizeof(MYCLASS) << endl; printf("m_i:%d\n", &MYCLASS原创 2021-07-24 00:35:22 · 153 阅读 · 0 评论 -
深度探索c++对象模型-12-单一继承下的数据成员布局
看如下代码:class parent{public: int m_i; int m_j;};class child :public parent{public: int m_k; int m_l;};void main(){ //打印偏移量 printf("parent::m_i = %d\n", &parent::m_i); printf("parent::m_j = %d\n", &parent::m_j); printf("parent::m_原创 2021-07-22 23:44:15 · 182 阅读 · 4 评论 -
深度探索c++对象模型-11-数据成员存取
一、静态成员变量的存取看如何修改变量值:其实这三句是没有任务区别的,看汇编:接下来看看各变量的地址:前面两个是普通变量,后面三个是静态变量:从结果可以看出,多次运行后,静态变量的地址是一直不变的。二、非静态成员变量的存取其实也就是普通的成员变量,存取通过类的对象(类对象指针)如下类:对于普通变量的访问,编译器是把类对象的首地址加上成员变量的偏移值。下面是个参考图:请看:转到汇编:m_i是首地址,在操作m_j的时候加了4,也就是偏移值,这个偏移值在编译的时候就原创 2021-07-22 00:16:30 · 179 阅读 · 1 评论 -
深度探索c++对象模型-10-数据成员布局
一、观察成员变量的地址规律先看如下的例子:接下来看m_i,m_k,m_j的存储顺序,注意在test中的定义顺序。然后打开内存,将t的地址输入进行,如下:从结果可以看出,经过t.m_i在最上面可以看到(红色部分)。接着继续执行,结果如下接续执行:从跟踪结果可以看出:普通变量的存储顺序,是按照在类中定义的顺序从上往下来的。结果:从运行结果可以看出对象中的地址是连续的。比较晚出现的成员变量在内存中有更高的地址。且类中public,private,protected的数量,不影响类对象原创 2021-07-20 22:39:04 · 210 阅读 · 1 评论 -
深度探索c++对象模型-09-进程内存空间布局
全局变量一般都放在数据段,且全局变量的地址是不变的。另外静态变量也是存储在数据段中的。如下代码:带有初值的在代码段,如int g4 = 32.没有初值的在bss段原创 2021-07-20 00:02:59 · 121 阅读 · 2 评论 -
深度探索c++对象模型-08-单纯的类不纯时引发的虚函数调用问题
如下是一个单纯的类(简单类):class test{public: int a; int b; int c; test() :a(0), b(0), c(0) { cout << "构造函数被执行\n"; } test(const test &o) :a(o.a), b(o.b), c(o.c) { cout << "拷贝构造函数被执行\n"; } void print() { cout << "a:" << a原创 2021-07-18 22:18:12 · 149 阅读 · 1 评论 -
深度探索c++对象模型-07-辅助工具分析虚函数表
1.看下面简单的代码:#include <iostream>using namespace std;class base1{public: virtual void f() { cout << "base1::f()\n"; } virtual void g() { cout << "base1::g()\n"; }};class base2{public: virtual void h() { cout <&原创 2021-07-18 00:00:32 · 159 阅读 · 2 评论 -
深度探索c++对象模型-06-多重继承函数表分析
先看代码分析:#include <iostream>using namespace std;class base1{public: virtual void f() { cout << "base1::f()\n"; } virtual void g() { cout << "base1::g()\n"; }};class base2{public: virtual void h() { cout <<原创 2021-07-15 23:18:29 · 255 阅读 · 2 评论 -
深度探索c++对象模型-05-虚函数表分析
总结:1.一个类只有包含虚函数才会存在虚函数表,同属于一个类的对象共享虚函数表。但是有各自的VPTR指针。当然各自的VPTR所只指向的地址(虚函数表地址)相同。2.分类中有虚函数,则子类一定有虚函数。 换句话:父类中有虚函数表,则子类中肯定有虚函数表。3.不管是父类还是子类,都只有一个虚函数表,不能认为子类中有一个虚函数表、父类中有一个虚函数表,就认为子类有两个虚函数表,这是错误的。4.如果子类中完全没有新的虚函数,则我们可以认为子的虚函数表和父类的虚函数表内容相同,当仅仅是内同相同,这两个表在..原创 2021-07-11 17:49:43 · 700 阅读 · 0 评论 -
深度探索c++对象模型-04-手动调用虚函数(多态实现原理)
如何手动调用虚函数呢?下面直接看代码一、代码#include <iostream>class Father{public: virtual void Func1() { std::cout << "Fahter::Func1()" << std::endl; } virtual void Func2() { std::cout << "Fahter::Func2()" << std::endl; } virtual原创 2021-06-29 23:29:26 · 333 阅读 · 3 评论 -
深度探索c++对象模型-03-VPTR在对象空间中的位置
看如下代码:class Test{public: char a; virtual void go() { }};void main(){ Test t; t.a = 'c'; cout << "sizeof(t):" << sizeof(t) << endl; char *ptra = reinterpret_cast<char *>(&t.a); char *ptrobj = reinterpret_cast<原创 2021-06-24 22:33:41 · 236 阅读 · 2 评论 -
深度探索c++对象模型-02-this指针调整
先看如下代码class A{public: int a; A() { printf("A::A()的this指针:%p!\n", this); } void funA() { printf("A::funA()的this指针:%p!\n", this); } };class B{public: int b; B() { printf("B::B()的this指针:%p!\n", this); } void funB() { printf(原创 2021-06-23 00:16:20 · 258 阅读 · 3 评论 -
深度探索c++对象模型-01-空类的大小、成员函数、成员变量的大小
一、空类大小class A{};void main(){ A a; cout <<"sizeof(a):"<< sizeof(a) << endl; system("pause");}结果:从结果可以看出,空类的大小是1,这是为了空类可以被实例化,并且每个实例在内存中都有独一无二的地址,因此,编译器会给空类隐含加上一个字节,这样空类实例化之后就会拥有独一无二的内存地址。如果没有这一个字节的占位,那么空类就无所谓实例化了,因为实例化的过程就原创 2021-06-20 13:20:20 · 395 阅读 · 0 评论