Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/55.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将结构划分为私有部分和公共部分? 在C++和java中,数据结构可以有私有< /代码>、公共和保护< /COD>区域。我想把这个概念移植到我正在编写的C语言程序中_C_Struct_Private Methods - Fatal编程技术网

将结构划分为私有部分和公共部分? 在C++和java中,数据结构可以有私有< /代码>、公共和保护< /COD>区域。我想把这个概念移植到我正在编写的C语言程序中

将结构划分为私有部分和公共部分? 在C++和java中,数据结构可以有私有< /代码>、公共和保护< /COD>区域。我想把这个概念移植到我正在编写的C语言程序中,c,struct,private-methods,C,Struct,Private Methods,在C结构中实现私有或受保护的函数指针和数据字段有什么习惯用法吗? 我知道Cstructs是公共的,我正在寻找一种习惯用法来帮助隐藏一些实现细节并强制用户使用公共接口 注意:该语言是由商店选择的,因此我一直坚持在C中实现面向对象的概念 谢谢。我为你感到遗憾,因为将不同的OO概念混入C中通常就像是一个方钉在圆孔中。话虽如此,GObject支持公共和私有成员,但它是我最不喜欢的体系结构之一。如果您不关心性能方面的小问题,那么您可能可以做一个更简单的解决方案—拥有一个填充了私有成员的二级结构,并拥有一个

在C
结构中实现私有或受保护的函数指针和数据字段有什么习惯用法吗?
我知道C
struct
s是公共的,我正在寻找一种习惯用法来帮助隐藏一些实现细节并强制用户使用公共接口

注意:该语言是由商店选择的,因此我一直坚持在C中实现面向对象的概念


谢谢。

我为你感到遗憾,因为将不同的OO概念混入C中通常就像是一个方钉在圆孔中。话虽如此,
GObject
支持公共和私有成员,但它是我最不喜欢的体系结构之一。如果您不关心性能方面的小问题,那么您可能可以做一个更简单的解决方案—拥有一个填充了私有成员的二级结构,并拥有一个从主(公共)结构指向该结构的匿名指针。

C中有时使用的概念是

// lib.h
typedef struct {
  int publicInt;
  //...
  char * publicStr;
} Public;

Public * getPublic();
int function(Public * public);

// lib.c

typedef struct {
  Public public;
  int privateInt;
  // ...
  char * privateStr
} Private;

static Private * getPrivate();

Public * getPublic() { return (Public*) getPrivate(); }
int function(Public * public) {
  Private * private = (Private *) public;
  // ...
}
这使用了一种标准技巧,即指向结构的指针可以与指向结构中第一个元素的指针互换

如果希望所有字段都是私有的,则更容易:

// lib2.h
typedef struct AllPrivate * Handle;
Handle getHandle();
int function2(Handle handle);

// lib2.c
struct AllPrivate { /* ... */ }
#包含
lib2.h的文件不会抱怨,因为我们只使用
struct AllPrivate*
,而且所有指针大小相同,因此编译器不需要知道
struct AllPrivate
的内部

要创建受保护区域,只需定义

// include/public.h
struct Public { /* ... */ }
struct Public * getPublic();
int somePublicFunction(struct Public *);

// dev/include/protected.h
struct Protected { struct Public public; /* ... */ }
struct Protected * getProtected();
int someProtectedFunction(struct Protected *);

// dev/src/private.c
struct Private { struct Protected protected; /* ... * /}
struct Public * getPublic() { return (struct Public *) getPrivate(); }
struct Public * getProtected() { return (struct Protected *) getPrivate(); }
int somePublicFunction(struct Public * public) { 
  struct Private private = (struct Private *) public;
  // ...
}
int someProtectedFunction(struct Protected * protected) { 
  struct Private private = (struct Private *) protected;
  // ...
}
然后,只需确保不传递
dev/include

对于数据字段,不要使用它们。你可以做一些小把戏,比如给它们取个疯狂的名字,以阻止它们的使用,但这并不能阻止人们。唯一真正的方法是创建另一个私有结构,该结构由库函数的void指针访问


对于私有函数——使用file
static
函数。将所有库函数放在一个C文件中,并将希望私有的库函数声明为
静态
,不要将它们放在任何头文件中。

如您所知,您不能这样做。然而,有些习语也会产生类似的效果

C将允许您执行类似于面向对象设计中的“pimpl”习惯用法的操作。您的结构可以有一个不透明指针,指向另一个作为结构私有数据的正向声明结构。在结构上操作的函数取代了成员函数,可以拥有私有成员的完整定义,并且可以使用它,而代码的其他部分则不能。例如:

在标题foo.h中:

  struct FooPrivate;

  struct Foo {
     /* public: */
       int x; 
       double y;
     /* private: */
       struct FooPrivate* p;
  };

  extern struct Foo* Foo_Create(); /* "constructor" */

  extern void Foo_DoWhatever(struct Foo* foo); /* "member function" */
在实现中,foo.c:

  struct FooPrivate {
     int z;
  };

  struct Foo* Foo_Create()
  {
     struct Foo* foo = malloc(sizeof(Foo));

     foo->p = malloc(sizeof(FooPrivate));

     foo->x = 0;
     foo->y = 0;
     foo->p->z = 0;

     return foo;
  }

  void Foo_DoWhatever(struct Foo* foo) 
  {
      foo->p->z = 4; /* Can access "private" parts of foo */
  }
在程序中:

  #include "foo.h"

  int main()
  {
      struct Foo* foo = Foo_Create();

      foo->x = 100; /* Can access "public" parts of foo */
      foo->p->z = 20; /* Error! FooPrivate is not fully declared here! */

      Foo_DoWhatever(foo); /* Can call "member" function */

      return 0;
  }
请注意,需要使用“构造函数”函数为私有数据分配内存。显然,您需要将其与一个特殊的“析构函数”配对,以便正确地解除分配私有数据

或者,如果您希望您的结构没有任何公共字段,您可以使整个结构不透明,只需将标题设置为

  struct Foo;

  extern struct Foo* Foo_Create(); /* "constructor" */

  extern void Foo_DoWhatever(struct Foo* foo); /* "member function" */

使用Foo.c中的
struct Foo
的实际定义,以及可用于您希望提供直接访问的任何属性的getter和setter函数。

通常按照惯例,私有成员的名称中会有一个额外的下划线,或者附加类似
\u pri
的内容。或者可能是评论。这种技术不会执行编译器强制的检查,以确保没有人不适当地访问这些字段,而是向任何阅读
struct
声明的人发出警告,内容是实现细节,他们不应该偷看或戳到它们

另一种常见的技术是将结构作为不完整类型公开。例如,在头文件中,您可能有:

struct my_struct;

void some_function(struct my_struct *);
在实现中,或库的使用者无法访问的某些内部标头中,您有:

struct my_struct
{
    /* Members of that struct */
};
您还可以使用void指针执行类似的操作,将其转换到代码“private”部分的正确位置。这种方法失去了一些灵活性(例如,您不能拥有未定义类型的堆栈分配实例),但这可能是可以接受的

如果希望混合使用私有成员和公共成员,可以执行与上面相同的操作,但将私有结构指针存储为公共结构指针的成员,并将其保留在库的公共使用者中

不过,这会引入一些间接操作,这可能会影响性能。您也可以使用一些类型双关技巧(通常是不可移植的,但可以在合理的编译器上使用):

struct public_struct
{
   int public_member;
   int public_member2;
   /* etc.. */
};

struct private_struct
{
   struct public_struct base_members;

   int private_member1;
   int private_member2;
};

void some_function(struct public_struct *obj)
{
   /* Hack alert! */
   struct private_struct *private = (struct private_struct*)obj;
}

这还假设您不能将这些对象存储在堆栈上或静态存储中,或在编译时获取其大小。

我想远离库包,因为这涉及许可问题,开发需要快速完成。(a)GObject是一个开源库,尽管不可否认,这可能会导致许可证问题;(b) 二级私有结构不需要库。+1谢谢你提醒我关于丘疹的习惯用法。我从来没有考虑过将它应用到C语言中。在C99中,您可能需要考虑用一个灵活的数组成员<代码> Strut FoopRivab[P][/Cord]替换指针为“代码>结构FoopRiVATE < /代码>。这将防止界面用户意外地创建
struct Foo
的浅层副本,因为这将使
struct Foo
成为一个不完整的类型。@caf您能详细说明使用灵活数组成员需要做哪些更改吗?分配将是
struct Foo*Foo=malloc(sizeof(struct Foo))+sizeof(struct FooPrivate))并且您不会尝试设置
foo->p
。一切