c - 什么是 C 语言中的编译时封装?

标签 c

当我研究 C 相对于 C++ 的优势时,我发现了这样一段话:

Standard way in C to do encapsulation is to forward declare a struct and only allow access to its data through functions. This method also creates compile time encapsulation. Compile time encapsulation allows us to change the data structures members without recompilation of client code (other code using our interface). The standard way of doing encapsulation C++ on the other hand (using classes) requires recompilation of client code when adding or removing private member variables.

我了解向前声明结构并通过函数访问其成员如何隐藏结构的实现细节。我不明白的是这一行具体是:

Compile time encapsulation allows us to change the data structures members without recompilation of client code (other code using our interface).

这适用于什么场景?

最佳答案

现实世界中可能发生这种情况的情况是,在硬盘空间非常有限的时代编写的数据库库使用单个字节来存储日期的“年份”字段(例如 11- NOV-1973 年的年份为 73)。但是,当 2000 年出现时,这将不再足够,年份必须存储为短(16 位)整数。该库的相关(非常简化) header 可能是这样的:

// dbEntry.h
typedef struct _dbEntry dbEntry;

dbEntry* CreateDBE(int day, int month, int year, int otherData);
void DeleteDBE(dbEntry* entry);
int GetYear(dbEntry* entry);

“客户端”程序是:

#include <stdio.h>
#include "dbEntry.h"

int main()
{
    int dataBlob = 42;
    dbEntry* test = CreateDBE(17, 11, 2019, dataBlob);
    //...
    int year = GetYear(test);
    printf("Year = %d\n", year);
    //...
    DeleteDBE(test);
    return 0;
}

“原始”实现:

#include <stdlib.h>
#include "dbEntry.h"

struct _dbEntry {
    unsigned char d;
    unsigned char m;
    unsigned char y;    // Fails at Y2K!
    int dummyData;
};

dbEntry* CreateDBE(int day, int month, int year, int otherData)
{
    dbEntry* local = malloc(sizeof(dbEntry));
    local->d = (unsigned char)(day);
    local->m = (unsigned char)(month);
    local->y = (unsigned char)(year % 100);
    local->dummyData = otherData;
    return local;
}

void DeleteDBE(dbEntry* entry)
{
    free(entry);
}

int GetYear(dbEntry* entry)
{
    return (int)(entry->y);
}

然后,在 Y2K 来临之际,此实现文件将更改如下(其他所有内容均保持不变):

struct _dbEntry {
    unsigned char d;
    unsigned char m;
    unsigned short y;   // Can now differentiate 1969 from 2069
    int dummyData;
};

dbEntry* CreateDBE(int day, int month, int year, int otherData)
{
    dbEntry* local = malloc(sizeof(dbEntry));
    local->d = (unsigned char)(day);
    local->m = (unsigned char)(month);
    local->y = (unsigned short)(year);
    local->dummyData = otherData;
    return local;
}

当客户端需要更新以使用新的(千年安全)版本时,不需要更改代码。事实上,您可能甚至不需要重新编译:只需重新链接到更新的对象库(如果是这样的话) 可能就足够了。

关于c - 什么是 C 语言中的编译时封装?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58900903/

相关文章:

c - 读取和写入内存位置

C++ 如何复制 FILE * 指针

c++ - OSX - 套接字连接重定向

c - C 编程中的堆内存

c++ - 这个声明 "float (*x[20])(int *a)"是什么意思?

c - 如何在 strsep() 之后释放内存?

c - YACC 生成的解析器对重复的相同输入给出不同的输出

c - 如何在不关闭套接字的情况下向主机发送 FIN 标志

c - Stack ADT实现中难以理解的表达

c -\% 和 %% 之间的区别