纯C中的getter和setter?

wdebmtf2  于 2023-08-03  发布在  其他
关注(0)|答案(3)|浏览(93)

我可以在纯C中使用getter和setter而不是使用extern变量吗?

sxissh06

sxissh061#

首先,不要听任何人说“x中没有面向对象”,因为他们真的不明白OO是一种 * 程序设计方法 *,完全脱离了语言语法。
有些语言有优雅的方法来实现OO,有些则没有。然而,用任何语言编写面向对象的程序都是可能的,for example in C。类似地,你的程序不会因为你用Java写的,或者因为你使用了某些语言关键字,就自动得到一个正确的OO设计。
在C中实现私有封装的方式比在支持OO的语言中实现的方式要粗糙一些,但它确实是这样的:
//module.h

void set_x (int n);
int get_x (void);

字符串
//模块. c

static int x; // private variable

void set_x (int n)
{
  x = n;
}

int get_x (void)
{
  return x;
}


//main.c

#include "module.h"

int main (void)
{
  set_x(5);
  printf("%d", get_x());
}


可以称之为“类”或“ADT”或“代码模块”。

这是所有合理的C程序都是这样写的。而且已经写了30-40年左右,只要程序设计已经存在。如果你说C程序中没有setter/getter,那是因为你没有使用C的经验。

编辑:为了完整起见,上面的线程安全的多示例版本也可以使用“opaque type”,请参阅How to do private encapsulation in C?

ecbunoof

ecbunoof2#

是的,这是非常可能的,有时甚至是有用的。C支持 opaque 类型:

struct Context;

字符串
在作用域中仅使用此声明编译的C代码不能访问结构体的任何假设成员,也不能使用Context类型的值。但是它仍然可以处理指向 * Context值的 * 指针,所以像这样的函数是可能的:

Context *make_context(...);
int context_get_foo(Context *);
void context_set_foo(Context *, int);


此模式将客户端C代码与Context的大小或内部布局的任何更改隔离开来。请注意,这比简单地声明但不记录成员更有保障:即使程序员适当地忽略了未文档化的成员,结构体的按值使用也是允许的(而且肯定会被滑进去),现在当大小改变时,代码必须重新编译。换句话说,仅通过指针处理的不透明类型给予了更大的ABI稳定性。

t8e9dugd

t8e9dugd3#

另一种方法是使用全局变量和内联函数:
//module.h

inline void set_x (int n) {extern int x; x = n;}
inline int get_x (void) {extern int x; return x;}

字符串
//模块. c

int x; // global variable


//main.c

#include "module.h"

int main (void)
{
  set_x(5);
  printf("%d", get_x());
}


它有两个优点:

  1. getter和setter变得容易内联
    1.编译器很清楚getter没有副作用,这允许进一步优化,并且在这种情况下不会产生警告:
    //警告:compound statement with side effects
if(get_x() || get_y())


当然,一个“专用”(读:dumb)程序员总是可以在他们的代码中编写extern int x;并直接使用该变量。另一方面,一个“专注”的程序员也可以很容易地删除static关键字并使用它。

相关问题