-
继承对象模型
-
在C++编译器的内部类可以理解为结构体
-
子类是由父类成员叠加子类新成语是你得到的
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++多态的实现原理
-
在类中声明虚函数时,编译器会在类中生成一个虚函数表
-
虚函数表是一个存储成员函数地址的数据结构
-
虚函数表是由编译器自动生成与维护的
-
vitrual成员函数会被编译器放入虚函数表
-
存在虚函数表,每个对象中都有一个指向虚函数表的指针
-
实现过程
void run(Demo*p,int v) { p->add(v); }
-
编译器确认add()是否为虚函数?
-
Yes->编译器在对象VPTR所指向的虚函数表中查找add()的地址
-
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); }
-
小结
-
继承的本质就是父子间成员变量的叠加
-
C++中的多态是通过虚函数表实现的
-
虚函数表是由编译器自动生成与维护的
-
虚函数的调用效率低于普通成员函数
原文链接: https://www.cnblogs.com/chengeputongren/p/12253721.html
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;
也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/326551
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!