MST

星途 面试题库

面试题:C语言接口设计中的信息隐藏原则应用

以一个简单的C语言项目为例,比如实现一个链表操作模块,描述如何依据信息隐藏原则来设计接口,使得其他模块只能通过特定接口访问链表数据,而无法直接操作链表内部结构。
12.5万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试
  1. 定义链表结构体
    • 在链表操作模块的源文件(比如list.c)中定义链表节点和链表的结构体,将其声明为static,这样在模块外部无法直接访问。
    static struct list_node {
        int data;
        struct list_node *next;
    };
    
    static struct list {
        struct list_node *head;
    };
    
  2. 接口函数设计
    • 初始化链表
      • 在头文件(比如list.h)中声明初始化链表的函数。
      struct list* list_init();
      
      • list.c中实现该函数。
      struct list* list_init() {
          struct list *new_list = (struct list*)malloc(sizeof(struct list));
          if (new_list == NULL) {
              return NULL;
          }
          new_list->head = NULL;
          return new_list;
      }
      
    • 插入节点
      • list.h中声明插入节点的函数,外部模块通过这个函数来向链表插入数据,而无需知道链表内部结构。
      int list_insert(struct list *list, int value);
      
      • list.c中实现该函数。
      int list_insert(struct list *list, int value) {
          struct list_node *new_node = (struct list_node*)malloc(sizeof(struct list_node));
          if (new_node == NULL) {
              return -1;
          }
          new_node->data = value;
          new_node->next = list->head;
          list->head = new_node;
          return 0;
      }
      
    • 删除节点
      • list.h中声明删除节点的函数。
      int list_delete(struct list *list, int value);
      
      • list.c中实现该函数。
      int list_delete(struct list *list, int value) {
          struct list_node *current = list->head;
          struct list_node *prev = NULL;
          while (current != NULL && current->data != value) {
              prev = current;
              current = current->next;
          }
          if (current == NULL) {
              return -1;
          }
          if (prev == NULL) {
              list->head = current->next;
          } else {
              prev->next = current->next;
          }
          free(current);
          return 0;
      }
      
    • 遍历链表
      • list.h中声明遍历链表的函数,外部模块可以通过这个函数获取链表数据,但无需了解链表内部结构。
      void list_traverse(struct list *list, void (*callback)(int));
      
      • list.c中实现该函数,这里callback是一个函数指针,用于处理遍历到的每个节点的数据。
      void list_traverse(struct list *list, void (*callback)(int)) {
          struct list_node *current = list->head;
          while (current != NULL) {
              callback(current->data);
              current = current->next;
          }
      }
      
  3. 头文件保护
    • list.h中使用头文件保护宏,防止头文件被重复包含。
    #ifndef LIST_H
    #define LIST_H
    
    struct list;
    struct list* list_init();
    int list_insert(struct list *list, int value);
    int list_delete(struct list *list, int value);
    void list_traverse(struct list *list, void (*callback)(int));
    
    #endif
    

通过以上设计,其他模块只能通过在list.h中声明的接口函数来访问链表数据,无法直接操作链表的内部结构,符合信息隐藏原则。