C 中的类模型

Ale*_*lex 1 c embedded struct class

我正在尝试用 C 语言创建一个“类模型”,其中我定义了一个struct代表类的对象,并在其中定义了函数指针来代表方法,如下所示:

//ClassName.h

typedef struct struct_ClassName ClassName;

struct ClassName
{

    
    char a;

    char b;

    char c;

    

    void (*method1)(ClassName*, char);

    void (*method2)(ClassName*, char);

    ...

    void (*methodN)(ClassName*, char);

};

void initClassName(ClassName*);

Run Code Online (Sandbox Code Playgroud)
//ClassName.c

#include "ClassName.h"

static void method1(ClassName *this_c, char c);
static void method2(ClassName *this_c, char c);
...
static void methodN(ClassName *this_c, char c);

void initClassName(ClassName *this_c)
{
    this_c->method1 = &method1;
    this_c->method2 = &method2;
    ...
    this_c->methodN = &methodN;
}

void method1(ClassName *this_c, char c)
{
    //do something
}

void method2(ClassName *this_c, char c)
{
    //do something
}

...


void methodN(ClassName *this_c, char c)
{
    //do something
}

Run Code Online (Sandbox Code Playgroud)

一切正常,但是在代码中的某个地方,我定义了一个数组:

...

ClassName objects[200];

for(i = 0; i < 200; i++)
{
    initClassName(&objects[i]);
}
...
Run Code Online (Sandbox Code Playgroud)

由于函数指针的原因,与该数组关联的内存使用量相当高(我在这个“类”中有几个“方法”)。

考虑到这是将在嵌入式系统中运行的代码,是否有更好的方法来做到这一点?

在结构之外定义函数可能是一种可能性,但在我看来,它不尊重我试图模仿的内容。

我必须只使用 C,而不是 C++ 。

Cod*_*odo 6

您创建的是一个非常动态的系统,其中每个对象实例都可以有自己的一组方法实现。这就是它使用这么多内存的原因。

另一种方法是更接近早期 C++(多重继承之前)的实现,其中同一类的所有实例共享相同的vtable。vtable包含函数指针

typedef struct struct_ClassName ClassName;

typedef struct struct_ClassName_vtable ClassName_vtable;

struct ClassName_vtable
{
    void (*method1)(ClassName*, char);
    void (*method2)(ClassName*, char);
    ...
    void (*methodN)(ClassName*, char);
}

struct ClassName
{
    ClassName_vtable* _vtable;
    
    char a;
    char b;
    char c;
};

void initClassName(ClassName*);
Run Code Online (Sandbox Code Playgroud)
static void method1(ClassName *this_c, char c);
static void method2(ClassName *this_c, char c);
...
static void methodN(ClassName *this_c, char c);

ClassName_vtable _ClassName_vtable = {
    method1,
    method2,
    ...,
    methodN
};

void initClassName(ClassName *this_c)
{
    this_c->_vtable = _ClassName_vtable;
}
Run Code Online (Sandbox Code Playgroud)

这样,每个实例的 OO 开销仅为指针的大小。创建子类也更容易。

方法调用如下所示:

ClassName* obj = ...;
obj->vtable->method2(obj, 'a');
Run Code Online (Sandbox Code Playgroud)