C++对象模型分析
文章目錄
- 1 class本質分析
- 1.1 class本質
- 2 非繼承對象模型分析
- 2.1 非繼承對象模型分析
- 3 繼承對象模型分析
- 3.1 繼承對象模型
- 3.2 多態對象模型
1 class本質分析
1.1 class本質
class是一種特殊的struct:
- 在內存中class依舊可以看作變量的集合。
- class與struct遵循相同的內存對齊規則。
- class中的成員函數與成員變量是分開存放的:
- 每個對象有獨立的成員變量。
- 所有對象共享類中的成員函數。
值得思考的問題:
對象內存布局初探:
運行時的對象退化為結構體的形式:
- 所有成員變量在內存中依次排布。
- 成員變量可能存在內存空隙。
- 可以通過內存地址直接訪問成員變量。
- 訪問權限關鍵字在運行時失效。
2 非繼承對象模型分析
2.1 非繼承對象模型分析
對象模型分析:
- 類中的成員函數位于代碼段中。
- 調用成員函數時對象地址作為參數隱式傳遞。
- 成員函數通過對象地址訪問成員變量。
- C++語法規則隱藏了對象地址的傳遞過程。
下面用C語言實現如下C++代碼:
#include <iostream> #include <string>using namespace std;class Demo {int mi;int mj; public:Demo(int i, int j){mi = i;mj = j;}int getI(){return mi;}int getJ(){return mj;}int add(int value){return mi + mj + value;} };int main() {Demo d(1, 2);cout << "sizeof(d) = " << sizeof(d) << endl;cout << "d.getI() = " << d.getI() << endl;cout << "d.getJ() = " << d.getJ() << endl;cout << "d.add(3) = " << d.add(3) << endl;return 0; }demo.h:
#ifndef _50_2_H_ #define _50_2_H_typedef void Demo;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);#endifdemo.c:
#include "50-2.h" #include "malloc.h"struct ClassDemo {int mi;int mj; };Demo* Demo_Create(int i, int j) {struct ClassDemo* ret = (struct ClassDemo*)malloc(sizeof(struct ClassDemo));if( ret != NULL ){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; }int Demo_Add(Demo* pThis, int value) {struct ClassDemo* obj = (struct ClassDemo*)pThis;return obj->mi + obj->mj + value; }void Demo_Free(Demo* pThis) {free(pThis); }main.c:
#include <stdio.h> #include "50-2.h"int main() {Demo* d = Demo_Create(1, 2); // Demo* d = new Demo(1, 2);printf("d.mi = %d\n", Demo_GetI(d)); // d->getI();printf("d.mj = %d\n", Demo_GetJ(d)); // d->getJ();printf("Add(3) = %d\n", Demo_Add(d, 3)); // d->add(3);// d->mi = 100;Demo_Free(d);return 0; }3 繼承對象模型分析
3.1 繼承對象模型
繼承對象模型:
- 在C++編譯器的內部類可以理解為結構體。
- 子類是由父類成員疊加子類新成員得到的。
3.2 多態對象模型
C++多態的實現原理:
- 當類中聲明虛函數時,編譯器會在類中生成一個虛函數表。
- 虛函數表是一個存儲成員函數地址的數據結構。
- 虛函數表是由編譯器自動生成與維護的。
- virtual成員函數會被編譯器放入虛函數表中。
- 存在虛函數時,每個對象中都有一個指向虛函數表的指針(位于最前面)。
繼承對象模型示例:
#include <iostream> #include <string>using namespace std;class Demo { protected:int mi;int mj; public:virtual void print(){cout << "mi = " << mi << ", "<< "mj = " << mj << endl;} };class Derived : public Demo {int mk; public:Derived(int i, int j, int k){mi = i;mj = j;mk = k;}void print(){cout << "mi = " << mi << ", "<< "mj = " << mj << ", "<< "mk = " << mk << endl;} };struct Test {void* p;int mi;int mj;int mk; };int main() {cout << "sizeof(Demo) = " << sizeof(Demo) << endl; cout << "sizeof(Derived) = " << sizeof(Derived) << endl; Derived d(1, 2, 3);Test* p = reinterpret_cast<Test*>(&d);cout << "Before changing ..." << endl;d.print();p->mi = 10;p->mj = 20;p->mk = 30;cout << "After changing ..." << endl;d.print();return 0; }用C語言實現多態特性:
demo.h:
demo.c:
#include "51-2.h" #include "malloc.h"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); }main.c:
#include "stdio.h" #include "51-2.h"void run(Demo* p, int v) {int r = Demo_Add(p, v);printf("r = %d\n", r); }int main() {Demo* pb = Demo_Create(1, 2);Derived* pd = Derived_Create(1, 22, 333);printf("pb->add(3) = %d\n", Demo_Add(pb, 3));printf("pd->add(3) = %d\n", Derived_Add(pd, 3));run(pb, 3);run(pd, 3);Demo_Free(pb);Demo_Free(pd);return 0; }參考資料:
總結
- 上一篇: C++中多态的概念和意义
- 下一篇: 国美零售拟以每股1.97港元配售22.8