lujw2 преди 11 месеца
родител
ревизия
fefc4652a2
променени са 1 файла, в които са добавени 95 реда и са изтрити 0 реда
  1. 95 0
      README.md

+ 95 - 0
README.md

@@ -0,0 +1,95 @@
+# 介绍
+实现C面向对象写法:
+1. `pointer`分支是基于函数指针的封装;
+2. `opaque`分支是不透明结构体的封装。
+
+# 与不透明结构体的对比
+## 1.基于函数指针的封装:
+- 优点:
+    - 模拟面向对象编程,使用方便,调用简洁。
+    - 函数指针可以灵活替换,允许不同实例有不同的行为(类似于多态)。
+    - 代码更具可读性,通过对象访问函数使得代码显得更加面向对象。
+- 缺点:
+    - 增加了一定的复杂性,尤其是在初始化、管理函数指针和内存管理时。
+    - 效率上可能会有轻微的开销,因为每次调用都要通过函数指针间接调用实际函数。
+    - 函数指针可能导致调试变得更困难(比如在使用调试器时,无法直接看到函数调用链)。
+
+## 2.不透明结构体(Opaque Struct):
+- 优点:
+    - 更简单和直接,库的用户不需要关心结构体内部的实现细节,增加了封装性和代码的安全性。
+    - 函数调用时更加直观,通过全局函数操作对象,用户只看到需要操作的API接口。
+    - 减少了复杂性,尤其在内存管理和函数指针管理方面更为轻量。
+- 缺点:
+    - 不能模拟对象方法调用,调用方式可能显得不够“面向对象”。
+    - 不支持多态:所有实例共享相同的函数,不能为不同实例设置不同的行为。
+
+# 工程中的使用情况
+在实际工程中,**不透明结构体(Opaque Struct)** 的方式通常使用得更多。
+尤其是在系统编程、嵌入式开发或跨平台库设计中,不透明结构体是更常见的设计模式。
+它的封装性好,内存管理相对简单,并且函数调用更加高效。
+这种模式通常用于C库的设计,比如许多操作系统API和标准库都会采用这种模式。
+## 不透明结构体(Opaque Struct)的实际例子
+1. POSIX标准中的文件操作(FILE 结构体):
+`FILE` 结构体就是一个经典的不透明结构体。
+用户通过API函数如 `fopen()`, `fclose()`, `fread()`, `fwrite()` 操作 `FILE` 指针,但无法直接访问 `FILE` 结构体的内部实现。
+```c
+FILE* file = fopen("test.txt", "r");
+if (file) {
+    // 使用 fread、fwrite 等函数操作 FILE 对象
+    fclose(file);
+}
+```
+2. OpenGL 的 GLFW 库:
+`GLFW` 是一个图形库,它大量使用了不透明结构体的设计。用户只能通过API函数操作这些结构体,如 `GLFWwindow`。
+```c
+GLFWwindow* window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
+if (window) {
+    // 使用 glfwGetWindowSize 等函数操作 GLFWwindow
+    glfwDestroyWindow(window);
+}
+```
+3. libcurl
+`libcurl` 使用了不透明结构体,库的用户通过 `CURL`* 指针操作 HTTP 请求,而无法直接访问内部数据。
+```c
+CURL *curl = curl_easy_init();
+if(curl) {
+    curl_easy_setopt(curl, CURLOPT_URL, "http://example.com");
+    curl_easy_perform(curl);
+    curl_easy_cleanup(curl);
+}
+```
+## 基于函数指针封装的实际例子
+这种模式较少见于系统编程或者底层库设计,但在某些场景中,例如模拟面向对象编程、插件系统或者策略模式时,这种模式非常有用。
+1. 插件系统(Plugin System):
+在许多插件系统中,插件往往通过一个统一的结构体接口暴露函数指针。
+这种设计可以允许不同的插件使用不同的行为,但又通过统一的接口进行交互。
+例如,音频处理库 FFmpeg 中的一些模块设计就是通过函数指针进行交互。
+```c
+struct Plugin {
+    void (*init)(void);
+    void (*process)(void);
+    void (*destroy)(void);
+};
+```
+2. `SDL(Simple DirectMedia Layer)`事件处理:
+虽然SDL本身大多数时候使用不透明结构体,但在处理回调函数时,类似于函数指针的设计非常常见。
+事件驱动系统通过将函数指针传递给SDL,可以自定义事件的处理逻辑。
+```c
+SDL_Event event;
+while (SDL_PollEvent(&event)) {
+    switch (event.type) {
+        case SDL_QUIT:
+            quit();
+            break;
+        case SDL_KEYDOWN:
+            keydown(event.key.keysym.sym);
+            break;
+    }
+}
+```
+
+# 总结
+- 不透明结构体(Opaque Struct) 是实际工程中更为常见的设计,特别是在需要跨平台和高效的API设计中。
+- 基于函数指针的封装 更适合在需要模拟面向对象行为,或需要为不同对象提供不同实现的场景。
+
+如果你的库需要高性能并且用户操作相对简单,`不透明结构体`是更合适的选择;而如果你希望提供面向对象的编程体验,可以考虑`基于函数指针的封装`。