对象对象模型:对象在内存是如何存放的
存放规则:
1. class内存对齐规则和struct相同。
2. class 成员函数和成员变量分开存放,每个对象有独享的成员变量(堆栈全局数据),同一类的所有对象共享同一成员函数(代码段)。
3. 调用成员函数时将对象地址传递给成员函数(隐式传递),成员函数通过对象地址(this指针)访问成员变量。
4. 对象只包含了成员变量,没有包含成员函数。
#include<iostream> #include<string> using namespace std; class A { int a; // 堆栈全局段 addr 0x7ffffc6795a0 int b; // 堆栈全局段 addr 0x7ffffc6795a4 char c; // 堆栈全局段 addr 0x7ffffc6795a8 double d; // 堆栈全局段 addr 0x7ffffc6795b0 public: void print() // 代码段 { cout << "addr of a = " << &a << endl; cout << "addr of b = " << &b << endl; cout << "addr of c = " << &c << endl; cout << "addr of d = " << &d << endl; } }; class B { int a; int b; char c; double d; public: void print() { cout << "addr of a = " << &a << endl; cout << "addr of b = " << &b << endl; cout << "addr of c = " << &c << endl; cout << "addr of d = " << &d << endl; } }; int main(void) { cout << "size of A = " << sizeof(A) << endl; A a; a.print(); B* p = reinterpret_cast<B*>(&a); // 通过地址可以直接访问修改private成员 p->a = 1; // private,protect,public关键字只在编译期有效 p->b = 2; // private,protect,public关键字只在运行期无效 p->c = 'c'; p->d = 3; a.print(); // 对象a的地址被传递到A类的print()函数。 return 0; }
继承对象模型:
1. 子类继承对象模型时父类成员叠加子类成员得到的。
2. 父类成员函数在代码段,子类对象成员函数也在代码段
#include <iostream> #include <string> using namespace std; class Parent { public: int a; int b;void print() { cout << "addr of a = " << &a << endl; // 0x7ffff70cea14 cout << "addr of b = " << &b << endl; // 0x7ffff70cea18 } }; class Child: public Parent { private: int c; public: void print() { cout << "addr of a = " << &a << endl; // 0x7ffff70cea1c cout << "addr of b = " << &b << endl; // 0x7ffff70cea20 cout << "addr of c = " << &c << endl; // 0x7ffff70cea24 } }; int main() { cout << " size of Parent = " << sizeof(Parent) << endl; // 8 cout << " size of Child = " << sizeof(Child) << endl; // 12 父类成员加子类成员
Parent p;
Child c;
p.print();
c.print();
return 0; }
多态的对象模型:
虚函数实现多态的原理:
1. 编译器为类创建一个虚函数表。
2. 对象定义一个指针指向虚函数表。
2. 虚函数表是存储指向虚函数的指针一个数据结构。
3. virtual 关键字定义的成员 函数会自动放入虚函数表。
多态调用时:p->vir_func(); p --> vptr --> vtable --> 0xff000111 函数调用 --> 虚函数表指针 --> 虚函数表中函数指针 --> 虚函数地址
#include <iostream> #include <string> using namespace std; class Parent { protected: int a; int b; public: virtual void print() { cout << "addr of a = " << &a << endl; //0x7fffdd1934d8 cout << "addr of b = " << &b << endl; // 0x7fffdd1934dc } }; class Child : public Parent { int c; public: void print() // 通过继承变也成虚函数 { cout << "there should be a address of virtual_table " << endl; // cout << "addr of a = " << &a << endl; // 0x7fffdd1934e8 cout << "addr of b = " << &b << endl; // 0x7fffdd1934ec cout << "addr of c = " << &c << endl; // 0x7fffdd1934f0 } }; struct Test { void* v_ptr; // 虚函数表指针 int a; int b; int c; }; int main() { Child c; Parent p; c.print(); p.print(); cout << "sizeof(Parent) = " << sizeof(Parent) << endl; // 16 = 4+4+8 8存放的是虚函数表地址 cout << "sizeof(Child) = " << sizeof(Child) << endl; // 24 = 4+4+4+(4)+8 8存放的是虚函数表地址 Test* test_p = reinterpret_cast<Test*>(&c); cout << " addr of virtual_table = " << &test_p->v_ptr << endl; // 0x7fffc0f14390 虚函数表指针存放在对象内存的最开始 cout << " addr of test.a = " << &test_p->a << endl; // 0x7fffc0f14398 cout << " addr of test.b = " << &test_p->b << endl; // 0x7fffc0f1439c cout << " addr of test.c = " << &test_p->c << endl; // 0x7fffc0f143a0 return 0; }
C语言实现多态:
#include "malloc.h" typedef void Demo; typedef void Derived; Demo* Demo_Create(int i, int j); int Demo_GetI(Demo* pThis); int Demo_GetJ(Demo* pThis); int Demo_Add(Demo* pThis, int value); void Demo_Free(Demo* pThis); Derived* Derived_Create(int i, int j, int k); int Derived_GetK(Derived* pThis); int Derived_Add(Derived* pThis, int value); static int Demo_Virtual_Add(Demo* pThis, int value); static int Derived_Virtual_Add(Demo* pThis, int value); struct VTable // 2. 定义虚函数表数据结构 { int (*pAdd)(void*, int); // 3. 虚函数表里面存储什么??? }; struct ClassDemo { struct VTable* vptr; // 1. 定义虚函数表指针 ==》 虚函数表指针类型??? int mi; int mj; }; struct ClassDerived { struct ClassDemo d; int mk; }; static struct VTable g_Demo_vtbl = { Demo_Virtual_Add }; static struct VTable g_Derived_vtbl = { Derived_Virtual_Add }; Demo* Demo_Create(int i, int j) { struct ClassDemo* ret = (struct ClassDemo*)malloc(sizeof(struct ClassDemo)); if( ret != NULL ) { ret->vptr = &g_Demo_vtbl; // 4. 关联对象和虚函数表 ret->mi = i; ret->mj = j; } return ret; } int Demo_GetI(Demo* pThis) { struct ClassDemo* obj = (struct ClassDemo*)pThis; return obj->mi; } int Demo_GetJ(Demo* pThis) { struct ClassDemo* obj = (struct ClassDemo*)pThis; return obj->mj; } // 6. 定义虚函数表中指针所指向的具体函数 static int Demo_Virtual_Add(Demo* pThis, int value) { struct ClassDemo* obj = (struct ClassDemo*)pThis; return obj->mi + obj->mj + value; } // 5. 分析具体的虚函数!!!! int Demo_Add(Demo* pThis, int value) { struct ClassDemo* obj = (struct ClassDemo*)pThis; return obj->vptr->pAdd(pThis, value); } void Demo_Free(Demo* pThis) { free(pThis); } Derived* Derived_Create(int i, int j, int k) { struct ClassDerived* ret = (struct ClassDerived*)malloc(sizeof(struct ClassDerived)); if( ret != NULL ) { ret->d.vptr = &g_Derived_vtbl; ret->d.mi = i; ret->d.mj = j; ret->mk = k; } return ret; } int Derived_GetK(Derived* pThis) { struct ClassDerived* obj = (struct ClassDerived*)pThis; return obj->mk; } static int Derived_Virtual_Add(Demo* pThis, int value) { struct ClassDerived* obj = (struct ClassDerived*)pThis; return obj->mk + value; } int Derived_Add(Derived* pThis, int value) { struct ClassDerived* obj = (struct ClassDerived*)pThis; return obj->d.vptr->pAdd(pThis, value); }
#include "stdio.h" typedef void Demo; typedef void Derived; Demo* Demo_Create(int i, int j); int Demo_GetI(Demo* pThis); int Demo_GetJ(Demo* pThis); int Demo_Add(Demo* pThis, int value); void Demo_Free(Demo* pThis); Derived* Derived_Create(int i, int j, int k); int Derived_GetK(Derived* pThis); int Derived_Add(Derived* pThis, int value); void run(Demo* p, int v) { int r = Demo_Add(p, v); printf("r = %d ", r); } int main() { Demo* pb = Demo_Create(1, 2); Derived* pd = Derived_Create(1, 22, 333); printf("pb->add(3) = %d ", Demo_Add(pb, 3)); printf("pd->add(3) = %d ", Derived_Add(pd, 3)); run(pb, 3); run(pd, 3); Demo_Free(pb); Demo_Free(pd); return 0; }