在C中抽象类型实现

St.*_*rio 1 c typedef header

我是C编程的新手并试图写一个简单的例子.我试图在类型实现上进行抽象,并简单地使用typedef和指定我可以对此类型执行的操作.我知道那时候类型是不完整的,但我打算把它完成到c-file,而不是标题.就这个:

test.h

#ifndef _TEST_H
#define _TEST_H

typedef my_type_t;

void init(my_type_t **t);

#endif //_TEST_H
Run Code Online (Sandbox Code Playgroud)

test.c

#include <stdlib.h>
#include "test.h"
                  //      implementation details
struct my_type_t{ //<---- completening my_type_t to be a struct with 1 field
    int field;
};

void init(struct my_type_t **t){ //<--- error: conflicting type for init
    *t = malloc(sizeof(struct my_type_t));
    (*t) -> field = 42;
}
Run Code Online (Sandbox Code Playgroud)

这样的事情可能吗?我希望实现完全隐藏有关实际类型定义的所有细节,只暴露可以用它完成的操作.

UPD:如果我们重写c-file如下:

#include <stdlib.h>
#include "test.h"

struct internal_my_type_definition_t{
    int field;
};

void init(my_type_t **t){
    struct internal_my_type_definition_t *st = malloc(sizeof(struct internal_my_type_definition_t));
    st -> field = 42;
    *t = st;
}
Run Code Online (Sandbox Code Playgroud)

这样的实现有什么问题吗?

nem*_*equ 5

在标题中,进行更改

typedef my_type_t;
Run Code Online (Sandbox Code Playgroud)

struct my_type_t;
Run Code Online (Sandbox Code Playgroud)

这是一种非常常见的模式.请记住,您需要一个函数来在堆上分配结构并释放它; 您隐藏的信息之一是结构的大小,因此API使用者实际上只能处理结构的指针而不是结构本身.

惯用的API就像是

struct my_type_t* my_type_new(void);
void my_type_free(struct my_type_t* self);
Run Code Online (Sandbox Code Playgroud)

my_type_init通常用于初始化已分配的实例,这实际上仅在您希望在*_new子类型的函数中链接到它时才有用.

编辑:为了回答您的后续问题,您可以想象在标题中执行以下操作:

#if !defined(MY_TYPE_NS)
#  define MY_TYPE_NS struct
#endif

typedef MY_TYPE_NS my_type_t my_type;

my_type* my_type_new(void);

/* ... */
Run Code Online (Sandbox Code Playgroud)

然后,在*.c文件中:

#define MY_TYPE_NS union
#include "test.h"

union my_type_t {
  /* ... */
};

my_type* my_type_new(void*) {
  my_type* res = malloc(sizeof(my_type));
  res->field = 42;
  return res;
}
Run Code Online (Sandbox Code Playgroud)

我觉得这只是一点点邪恶.我可能只是使用嵌套在结构内部的联合来避免代码中的任何意外.