模仿面向对象的ansi c使用函数指针内部结构或使用函数外部

r1zhe5dt  于 2023-03-29  发布在  其他
关注(0)|答案(1)|浏览(111)

我正在尝试用C语言编写OOP,但面临着两种方法:

#ifndef __TREE_H__
#define __TREE_H__

#include "types.h"
#include "interface.h"

typedef struct _tree_t tree_t;

tree_t* tree_create(int (*compare_fn)(void *o1, void *o2),
                    void* (*copy_fn)(void *o),
                    void (*dealloc_fn)(void *o),
                    iallocator_t *iallocator);

void tree_delete(tree_t *t);

void tree_add_object(tree_t *t, void *o);

void* tree_fnd_object(tree_t *t, void *o);

void* tree_rmv_object(tree_t *t, void *o);

void tree_print(tree_t *t, void (*print_fn)(void *o));

void tree_balance_DSW(tree_t *t);

#endif /* __TREE_H__ */

第二:

#ifndef __TREE_H__
#define __TREE_H__

#include "types.h"
#include "interface.h"

typedef struct _tree_t tree_t;

typedef struct _tree_t
{
    void (*add_object)(tree_t *self, void *o);
    void* (*fnd_object)(tree_t *self, void *o);
    void* (*rmv_object)(tree_t *self, void *o);
    void (*print)(tree_t *self, void (*print_fn)(void *o));
    void (*balance_DSW)(tree_t *self);
   
    void* private;
};

tree_t* tree_create(int (*compare_fn)(void *o1, void *o2),
                    void* (*copy_fn)(void *o),
                    void (*dealloc_fn)(void *o),
                    iallocator_t *iallocator);

void tree_delete(tree_t *t);

#endif /* __TREE_H__ */

所以我不知道什么方式更灵活,更好的设计方面,有人能给予我一个建议吗?
因为现在很难理解什么会更好

tct7dpnv

tct7dpnv1#

在这两者之间有一个解决方案,它将为每个树对象保存大量内存,并允许以更C++的方式调用方法。
只需引入tree_ops_t结构体,它允许在所有tree_t对象之间共享接口:

typedef struct tree_t tree_t;

struct tree_ops_t {
    void (*add_object)(tree_t *self, void *o);
    void* (*fnd_object)(tree_t *self, void *o);
    void* (*rmv_object)(tree_t *self, void *o);
    void (*print)(tree_t *self, void (*print_fn)(void *o));
    void (*balance_DSW)(tree_t *self);
};

struct tree_t {
    const struct tree_ops_t *ops;
    void *private;
};

static const tree_ops_t tree_ops = {
  ... set all callbacks here
};

tree_t* tree_create(...) {
   tree_t *t;
   ...
   t->ops = &tree_ops;
}

现在这些方法的调用方式如下:

t->ops->add_object(t, NULL);

顺便说一句。
typeof扩展(即将到来的C23中的一个特性)的帮助下,从函数类型派生的类型的语法可以稍微美化一下。

void (*balance_DSW)(tree_t *self);

变成

typeof(void(tree_t)) *balance_DSW;

可以说,它可能更容易阅读,特别是对于返回复杂类型。
此外,当传递函数指针作为参数时,您可以利用“函数衰减”机制,其中函数类型被转换为函数指针类型。

void print(tree_t *self, void (*print_fn)(void*));

等同于:

void print(tree_t *self, void print_fn(void*));

相关问题