封装

隐藏内部数据,只暴露接口函数。

"头文件"暴露的内容

typedef struct BankAccount BankAccount;  // 前向声明,不暴露成员

// 只暴露函数接口
BankAccount* BankAccount_open(const char* owner, double balance);
void         BankAccount_deposit(BankAccount* a, double amount);
int          BankAccount_withdraw(BankAccount* a, double amount);
double       BankAccount_get_balance(const BankAccount* a);
const char*  BankAccount_get_owner(const BankAccount* a);
void         BankAccount_close(BankAccount* a);

"实现" —— 结构体完整定义对外不可见

struct BankAccount {
    char   owner[32];
    double balance;       /* 外部无法直接访问 */
    int    active;        /* 完全隐藏 */
    int    failed_count;  /* 对外不可见 */
};

函数实现

BankAccount* BankAccount_open(const char* owner, double balance) {
    BankAccount* a = malloc(sizeof(BankAccount));
    if (a) {
        strncpy(a->owner, owner, sizeof(a->owner) - 1);
        a->owner[sizeof(a->owner) - 1] = '\0';
        a->balance      = balance;
        a->active       = 1;
        a->failed_count = 0;
    }
    return a;
}

void BankAccount_deposit(BankAccount* a, double amount) {
    if (a->active && amount > 0) {
        a->balance += amount;
    }
}

int BankAccount_withdraw(BankAccount* a, double amount) {
    if (!a->active) return -1;
    if (amount > a->balance) {
        a->failed_count++;       // 记录失败次数,外部无感知
        return -1;
    }
    a->balance -= amount;
    return 0;
}

double BankAccount_get_balance(const BankAccount* a) {
    return a->balance;
}

const char* BankAccount_get_owner(const BankAccount* a) {
    return a->owner;
}

void BankAccount_close(BankAccount* a) {
    if (a) {
        a->active = 0;
        printf("[internal] failed_count=%d\n", a->failed_count);
        free(a);
    }
}

使用者视角

int main(void) {
    BankAccount* acc = BankAccount_open("Alice", 1000.0);
    BankAccount_deposit(acc, 500.0);
    BankAccount_withdraw(acc, 200.0);

    // 只能通过函数访问,无法 acc->balance 或 acc->failed_count
    printf("owner: %s\n",   BankAccount_get_owner(acc));
    printf("balance: %.2f\n", BankAccount_get_balance(acc));

    BankAccount_close(acc);
    return 0;
}

C 的封装靠"文件作用域 + 不透明指针"实现,而非 private 关键字。