我正在尝试实现一个struct person,我需要隐藏一些字段或使其保持不变。 创建私有字段的技巧。
标头:
#pragma once
#define NAME_MAX_LEN 20
typedef struct _person {
float wage;
int groupid;
} Person;
const char const *getName (Person *p);
int getId (Person *p);
/// OTHER FUNCTIONS
Run Code Online (Sandbox Code Playgroud)
资源
#include "person.h"
struct _person
{
int id;
float wage;
int groupid;
char name[NAME_MAX_LEN];
};
/// FUNCTIONS
Run Code Online (Sandbox Code Playgroud)
海湾合作委员会说 person.c:7:8: error: redefinition a 'struct _person' struct _person
我可以将其写在标题中,但是在此之后,就不能使用结构的字段。
typedef struct _person Person;
Run Code Online (Sandbox Code Playgroud)
dbu*_*ush 24
一个结构不能有多个冲突的定义。因此,您无法创建隐藏某些字段的结构。
但是,您可以做什么,但声明该结构存在于标头中而不定义它。然后,调用方被限制为仅使用指向该结构的指针,并在实现中使用函数对其进行修改。
例如,您可以按以下方式定义标题:
typedef struct _person Person;
Person *init(const char *name, int id, float wage, int groupid);
const char *getName (const Person *p);
int getId (const Person *p);
float getWage (const Person *p);
int getGroupid (const Person *p);
Run Code Online (Sandbox Code Playgroud)
您的实现将包含:
#include "person.h"
struct _person
{
int id;
float wage;
int groupid;
char name[NAME_MAX_LEN];
};
Person *init(const char *name, int id, float wage, int groupid)
{
Person *p = malloc(sizeof *p);
strcpy(p->name, name);
p->id = id;
p->wage= wage;
p->groupid= groupid;
return p;
}
...
Run Code Online (Sandbox Code Playgroud)
Joh*_*ger 17
C没有隐藏结构类型的单个成员的机制。但是,通过仅根据指向这种类型的指针进行操作而不提供定义,可以使整个类型不透明。然后,用户将不得不使用您提供的功能以任何方式操纵实例。这是有时要做的事情。
在某种程度上,您可以实现类似于您在隐藏上下文中描述的内容。例如,考虑一下:
头文件
typedef struct _person {
float wage;
int groupid;
} Person;
Run Code Online (Sandbox Code Playgroud)
实施
struct _person_real {
Person person; // must be first, and is a structure, not a pointer.
int id;
char name[NAME_MAX_LEN];
};
Run Code Online (Sandbox Code Playgroud)
现在您可以执行以下操作:
Person *create_person(char name[]) {
struct _person_real *pr = malloc(sizeof(*pr));
if (pr) {
pr->person.wage = DEFAULT_WAGE;
pr->person.groupid = DEFAULT_GROUPID;
pr->id = generate_id();
strncpy(pr->name, name, sizeof(pr->name));
pr->name[sizeof(pr->name) - 1] = '\0';
return &pr->person; // <-- NOTE WELL
} else {
return NULL;
}
}
Run Code Online (Sandbox Code Playgroud)
指向结构的第一个成员的指针也总是也指向整个结构,因此,如果客户端将从该函数获得的指针传递回给您,则可以
struct _person_real *pr = (struct _person_real *) Person_pointer;
Run Code Online (Sandbox Code Playgroud)
并从更大的范围对成员进行工作。
但是,请注意,这样的方案存在风险。没有什么可以阻止用户在Person 没有较大上下文的情况下创建,并将指向它的指针传递给期望存在上下文对象的函数。还有其他问题。
总体而言,C API通常采用不透明的结构方法,或者只是仔细地记录允许客户使用其访问的数据做什么,甚至只是记录一切如何工作,以便用户可以做出自己的选择。这些方法,尤其是后者,与整体C方法和习惯用法完全吻合-C不能握住您的手,或保护您免受伤害。它信任您知道您在做什么,并且仅执行您打算做的事情。