这是我的设置:

在public.h中:

#ifndef PUBLIC_H_
#define PUBLIC_H_

#include "func.h"

/*extern typedef struct _my_private_struct PRIVATE_;*/
typedef struct _my_private_struct PRIVATE_; /* Thanks to larsmans and Simon Richter */
#endif

在struct.h中
#ifndef STRUCT_H_
#define STRUCT_H_

struct _my_private_struct {
    int i;
};
#endif

在func.h中:
#ifndef FUNC_H_
#define FUNC_H_
#include "struct.h"

/* typedef struct _my_private_struct PRIVATE_; */
extern PRIVATE_ * get_new(int);
#endif

在func.c中:
#include <stdlib.h>
#include "func.h"

PRIVATE_ * get_new(int i)
{
    PRIVATE_ *p = (PRIVATE_ *) malloc(sizeof(PRIVATE_));
    if (p == NULL) return NULL;

    p->i = i;

    return p;
}

在main.c中:
#include "public.h"

int main(int argc, char ** argv)
{
    PRIVATE_ *p = get_new(2);
    return 0;
}

当我使用GCC编译这些文件时,出现此错误:

旧的编译错误



编辑后编译错误



有人可以帮助我/解释为什么我得到了它以及如何解决它吗?

最佳答案

其他答案很好地解决了您的问题。但是,请允许我添加到其中并回答您的最新评论:



虽然错误是不言自明的,但可能不清楚原因为何。考虑一下当包含public.h时会发生什么:

#include "struct.h"
#include "func.h"
typedef struct _my_private_struct PRIVATE_;

如果您对此进行跟踪并充分扩展了预处理器,那么您将获得:
// struct.h
struct _my_private_struct
{
    int i;
};

// func.h
typedef struct _my_private_struct PRIVATE_;
extern PRIVATE_ * get_new(int);

// public.h
typedef struct _my_private_struct PRIVATE_;

现在应该很清楚为什么会遇到问题。在func.h中没有typedef的情况下,您的get_new原型(prototype)将失败,因为它尚未看到PRIVATE。 OTOH,如果您将typedef保留在其中,则需要定义两次。

同样,您似乎正在尝试将该结构与其他代码和模块相对私有(private)。即使您确实修复了构建错误,也并没有真正实现该封装。考虑一下:
int main()
{
    PRIVATE_ *p = get_new(2);
    p->i = 1337;        // HAHA, I just modified your private i.
                        // what are you going to do about it?
}

如果要使用C进行数据保密,请考虑使用不透明的指针设计。我建议像这样重组您的源:
// public.h
#ifndef PUBLIC_H_
#define PUBLIC_H_

#include "func.h"

#endif
// func.h
#ifndef FUNC_H_
#define FUNC_H_

struct PRIVATE_NOT_ACCESSIBLE;
typedef struct PRIVATE_NOT_ACCESSIBLE myint_t;

// declare your struct methods here
myint_t* get_new(int);
// ..

#endif
// func.c
#include <stdlib.h>
#include "func.h"

// define this only with functions
// that's suppose to work with its internal data
struct PRIVATE_NOT_ACCESSIBLE
{
    int i;
};

myint_t * get_new(int i)
{
  // ...
}

现在,如果您尝试这样做:
#include "public.h"

int main()
{
    myint_t *p = get_new(2);
    p->i = 1337;            // Aw, doesn't work anymore :(
}

编辑:回答以下OP的评论。

如果您在多个编译单元中实现了私有(private)结构的方法,则仍可以通过将私有(private)定义移至专用 header 来使其工作:
// func_implementation.h
#include "func.h"
struct PRIVATE_NOT_ACCESSIBLE
{
    int i;
};
// internal methods, helper functions you don't want exposed should go here too.
// eg.
void helper_method(myint_t *);

实现您的结构私有(private)“对象”的源文件将包含“func_implementation.h”。使用私有(private)的外部客户端代码将仅包含“func.h”。

10-07 19:08
查看更多