C++对象模型分析(下)

  • 继承对象模型
  1. 在C++编译器的内部类可以理解为结构体
  2. 子类是由父类成员叠加子类新成语是你得到的
class Derived:public Demo
{
    int mk;
};
  • 实验验证
 1 // 继承对象内存模型.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
 2 //
 3 #include <iostream>
 4 #include <string>
 5 using namespace std;
 6 class Demo
 7 {
 8 protected:
 9     int mi;
10     int mj;
11 };
12 class Derived : public Demo
13 {
14     int mk;
15 public:
16     Derived(int i,int j,int k)
17     {
18         mi = i;
19         mj = j;
20         mk = k;
21     }
22     void print()
23     {
24         cout << "mi=" << mi << endl
25              << "mj=" << mj << endl
26              << "mk=" << mk << endl;
27     }
28 };
29 //说明子类的内存布局和这个结构体是一样的
30 struct Test
31 {
32     int mi;
33     int mj;
34     int mk;
35 };
36 int main()
37 {
38     Derived d(1,2,3);
39     cout << "sizeof(Demo)=" << sizeof(Demo) << endl;
40     cout << "sizeof(Derived)=" << sizeof(Derived) << endl;
41     cout << "Before changing..." << endl;
42     d.print();
43     Test* p = reinterpret_cast<Test*>(&d);
44     p->mi = 10;
45     p->mj = 20;
46     p->mk = 30;
47     cout << "After changing" << endl;
48     //说明了,子类的内存布局和Test结构体一样。
49     d.print();
50 }
  • 运行结果
sizeof(Demo)=8
sizeof(Derived)=12
Before changing...
mi=1
mj=2
mk=3
After changing
mi=10
mj=20
mk=30
  • 多态对象模型
  • C++多态的实现原理
  1. 在类中声明虚函数时,编译器会在类中生成一个虚函数表
  2. 虚函数表是一个存储成员函数地址的数据结构
  3. 虚函数表是由编译器自动生成与维护的
  4. vitrual成员函数会被编译器放入虚函数表
  5. 存在虚函数表,每个对象中都有一个指向虚函数表的指针
  • 实现过程
void run(Demo*p,int v)
{
    p->add(v);
}
  • 编译器确认add()是否为虚函数?
  1. Yes->编译器在对象VPTR所指向的虚函数表中查找add()的地址
  2. No-> 编译器可以直接确定被调成员函数的地址
  • 用C语言实现面向对象,继承,多态
OOP. h
 1 #ifndef _OOP_H_
 2 #define _OOP_H_
 3 typedef void DEMO;
 4 typedef void DERIVED;
 5 struct FATHER_OBJECT
 6 {
 7         struct Virtual_Table* _ptr;
 8         int value1;
 9         int value2;
10 };
11 struct SON_OBJECT
12 {
13         struct FATHER_OBJECT _obj;
14         int value3;
15 };
16 //虚函数表
17 struct Virtual_Table
18 {
19         void (*virtual_function)(void*);
20 };
21 /*-------------------父类--------------*/
22 //【step1】模拟C++的构造函数,需要返回this指针
23 DEMO* Great_Father_Object(int i,int j);
24 //【step2】定义成员函数,获取成员变量的值,需要传递对象的地址
25 int GET_Value1(DEMO* pthis);
26 //【step2】定义成员函数,获取成员变量的值,需要传递对象的地址
27 int GET_Value2(DEMO* pthis);
28 //......
29 //【step3】模拟C++中的析构函数
30 void Free_Father_Object(DEMO* pthis);
31 //父类虚函数
32 void Father_print(DEMO*pthis);
33 void DEMO_Virtual_Function(DEMO* pthis);
34 /*----------------子类-----------------*/
35 DERIVED* Great_Son_Object(int i,int j,int k);
36 int GET_Value3(DERIVED* pthis);
37 void Free_Son_Object(DERIVED* pthis);
38 //子类虚函数
39 void Son_print(DERIVED*pthis);
40 void DERIVED_Virtual_Function(DERIVED* pthis);
41 static struct Virtual_Table Fa =
42 {
43         DEMO_Virtual_Function
44 };
45 static struct Virtual_Table So =
46 {
47         DERIVED_Virtual_Function
48 };
49 #endif
 OOP.c
#include "OOP.h"
#include "stdio.h"
#include "malloc.h"
DEMO* Great_Father_Object(int i, int j)
{
        struct FATHER_OBJECT* Object = (struct FATHER_OBJECT*)malloc(sizeof(struct  FATHER_OBJECT));
        if (Object!=NULL)
        {       
               Object->_ptr = &Fa;
               Object->value1 = i;
               Object->value2 = j;
        }
        return Object;
}
int GET_Value1(DEMO* pthis)
{
        struct FATHER_OBJECT* ret = (struct FATHER_OBJECT*)pthis;
        return ret->value1;
}
int GET_Value2(DEMO* pthis)
{
        struct FATHER_OBJECT* ret = (struct FATHER_OBJECT*)pthis;
        return ret->value2;
}
void Free_Father_Object(DEMO* pthis)
{
        free(pthis);
}
void Father_print(DEMO* pthis)
{
        struct FATHER_OBJECT* THIS = (struct FATHER_OBJECT*)pthis;
        THIS->_ptr->virtual_function(THIS);
}
void DEMO_Virtual_Function(DEMO* pthis)
{
        printf("I'm Demo\n");
}
DERIVED* Great_Son_Object(int i, int j, int k)
{
        struct SON_OBJECT* Object = (struct SON_OBJECT*)malloc(sizeof(struct SON_OBJECT));
        if (Object != NULL)
        {
               Object->_obj._ptr = &So;
               Object->_obj.value1 = i;
               Object->_obj.value2 = j;
               Object->value3 = k;
        }
        return Object;
}
int GET_Value3(DERIVED* pthis)
{
        struct SON_OBJECT* ret = (struct SON_OBJECT*)pthis;
        return ret->value3;
}
void Free_Son_Object(DERIVED* pthis)
{
        free(pthis);
}
void Son_print(DERIVED* pthis)
{
        struct SON_OBJECT* THIS = (struct SON_OBJECT*)pthis;
        THIS->_obj._ptr->virtual_function(THIS);
}
void DERIVED_Virtual_Function(DERIVED* pthis)
{
        printf("I'm Derived\n");
}
main.c
#include "stdio.h"
#include "OOP.h"
void run(DEMO*pthis)
{
        Father_print(pthis);
}
int main()
{
#if 0
        DEMO* THIS = NULL;
        //【step1】执行“构造函数”
        THIS = (struct FATHER_OBJECT*)Great_Father_Object(1,2);
        //【step2】执行成员函数,成员函数必须带有对象地址,通过对象地址访问成员变量
        printf("THIS->value1=%d\n", GET_Value1(THIS));
        printf("THIS->value2=%d\n", GET_Value2(THIS));
        //【step3】执行“析构函数”
        Free_Father_Object(THIS);
#endif
        DEMO* d;
        DERIVED* p;
        d = (struct FATHER_OBJECT*)Great_Father_Object(1, 2);
        p = (struct SON_OBJECT*)Great_Son_Object(1, 22,333);
        printf("p->value1=%d\n", GET_Value1(p));
        printf("p->value2=%d\n", GET_Value2(p));
        printf("p->value3=%d\n",GET_Value3(p));
        run(d);
        run(p);
        Free_Son_Object(p);
        Free_Father_Object(d);
}
  • 小结
  1. 继承的本质就是父子间成员变量的叠加
  2. C++中的多态是通过虚函数表实现的
  3. 虚函数表是由编译器自动生成与维护的
  4. 虚函数的调用效率低于普通成员函数
 
 
 
posted @ 2020-02-02 21:10  认真做个普通人  阅读(214)  评论(0编辑  收藏  举报