C++对象模型
C++类中一般包含两种数据成员和三中函数成员
- 非静态数据成员
- 静态数据成员
- 非静态成员函数
- 静态成员函数
- 虚函数
在类的每个实例化对象中,只包含两种数据,非静态数据成员和指向虚函数表(virtual table)的指针(vptr)
继承的内存模型
在不考虑多态的情况下,也就只考虑继承过程中的非静态数据成员的内存模型就可以了。
在C++中,每个子类对象的内存空间中包含所有的父类的非静态数据成员。
base class data |
---|
other data members |
C语言继承实现
只要实现和C++继承一样的内存模型就可以了
typedef struct _base {
float x;
} Base;
typedef struct _D {
Base base;
float y;
}D;
D *new_D() { ... return x; }
这样形成的内存模型就符合要求了。
Base * base = (Base *)new_D();
C语言多态实现
C++使用虚函数实现的动态多态,是在运行时根据类型进行判断绑定的。
C语言要实现多态,就需要在创建时手动绑定了。
C语言继承与多态示例
#include <stdio.h>
#include <stdlib.h>
typedef void (*func)(void);
// 模拟虚函数表
struct _vptr {
func foo;
};
// 基类
typedef struct _base {
float x;
struct _vptr *vptr;
} Base;
// 继承Base
typedef struct _A {
Base base;
float a;
}A;
// 继承Base
typedef struct _B {
Base base;
float b;
}B;
// 根据内存模型和截断规则,无论继承多少层都可以使用该宏直接访问'虚函数表'
#define VPTR(ob) (((Base *)(ob))->vptr)
void A_foo()
{
printf("<type 'A'>\n");
}
void B_foo()
{
printf("<type 'B'>\n");
}
struct _vptr A_vptr = { A_foo };
struct _vptr B_vptr = { B_foo };
// 构造函数
A * new_A()
{
A * a = (A*)malloc(sizeof(A));
VPTR(a) = &A_vptr;
return a;
}
B * new_B()
{
B * b = (B*)malloc(sizeof(B));
VPTR(b) = &B_vptr;
return b;
}
// 释放,相当于析构函数
void _delete(void * ptr) { free(ptr); }
///
// 使用
int main(void)
{
A * a = new_A();
B * b = new_B();
Base * base_A = (Base *)a;
Base * base_B = (Base *)b;
base_A->vptr->foo();
base_B->vptr->foo();
_delete(a);
_delete(b);
return 0;
}