【问题标题】:Getters and setters in pure C?纯C中的getter和setter?
【发布时间】:2015-02-03 15:26:36
【问题描述】:

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

【问题讨论】:

    标签: c setter getter


    【解决方案1】:

    首先,不要听任何人说“x语言没有面向对象”,因为他们真的不明白OO是一种程序设计方法,完全脱离了语言句法。

    有些语言有优雅的方式来实现 OO,有些则没有。然而,可以使用任何语言编写面向对象的程序,for example in C。同样,您的程序不会因为您使用 Java 编写或使用某​​些语言关键字而自动获得正确的 OO 设计。

    在 C 中实现私有封装的方式比在支持 OO 的语言中要粗略一些,但它确实是这样的:

    //模块.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 的经验。

    【讨论】:

    • 是的,这正是我试图理解的:这些方法(静态变量+'C 风格的 getter' 和简单的'变量+外部声明')是绝对可替代的,还是更可取?
    • @giorgim 同样,但如果变量类型必须暴露给调用者,您必须通过不完整(“不透明”)类型来实现它,如另一个答案中所述。
    • @giorgim 正式术语是不完整类型,基本上意思是“这里是一个类型,我会在别处解释它是如何定义的”。在h文件里面,类型定义是未知的,调用者也是未知的。不过,您可以在不知道内容的情况下使用指向此类型的指针。您不能声明该类型的变量,也不能访问其内容。 (如果您熟悉 C++,则其工作方式与抽象基类完全一样。)
    • @giorgim 如链接的示例所示,只需在 h 文件中声明一个没有定义的结构:typedef struct engine_t engine_t;,然后只在 c 文件中定义它。这样调用者将可以访问结构声明(类型名称),但不能访问定义(内容)。
    【解决方案2】:

    是的,这很有可能,有时甚至很有用。 C 支持 不透明 类型:

    struct Context;
    

    在范围内仅使用此声明编译的 C 代码不能访问结构的任何假设成员,也不能使用 Context 类型的值。但它仍然可以处理 指向 Context 值的指针,因此可以使用以下函数:

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

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

    【讨论】:

    • 不透明类型是实现结构真正私有封装的好方法,它绝对是专业 C 程序员的必经之路。但是 opaque 类型并不是仅仅为了声明一些私有变量并为它们实现 setter/getter 所必需的,请参阅我的答案以获得一种简化的方法。
    • @Lundin 你所描述的也有效,确实更简单,甚至可能更接近 OP 的要求(鉴于他们提到了extern)。但我不会将其称为“简化方式”,因为它是一种完全不同的工具,就像 Java 中的 static 成员不是“简化”实例成员一样。
    • 现在说如果我绝对不需要在项目中使用不透明结构,我应该使用“静态变量+getters”来拥有专业风格,或者是否使用无关紧要吗?这是通过“外部声明”从其他模块直接访问还是直接访问?
    • @elusive 你应该使用 static + setter/getters。 extern 全局变量是非常糟糕的做法,被认为是“意大利面条编码”。事实上,在 C 语言中没有任何理由使用 extern 关键字。
    • @elusive 除非项目一团糟,否则最好保持原样。只需确保您生成的所有新代码都不包含此类全局变量。
    猜你喜欢
    • 1970-01-01
    • 2010-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-27
    • 2015-02-03
    • 1970-01-01
    相关资源
    最近更新 更多