C语言 利用 不透明指针 实现封装特性

参考文章

前言

面向对象三大特性是 封装 - 继承 - 多态

面向对象三大特性 :

  • 封装 ( Encapsulation ) : 将 数据 和 操作数据的方法 包装在一起 , 隐藏 数据的内部细节 , 防止外界的直接访问和修改 ;
    封装后 , 只能通过 对外提供的接口 , 对 封装在内部的属性和方法 进行 访问和操作 ;
  • 继承 ( Inheritance ) : 让 一个 实例对象 获取 另一个 实例对象 的 属性 和 方法 , 在不重写现有代码的基础上实现代码的重用 ;
    继承可以 实现出 类的层次结构 , 可以 扩展 现有父类的功能 ;
  • 多态 ( Polymorphism ) : 不同的 实例对象 对 想通的消息 作出不同响应 , 也就是调用想通类型实例对象 的 方法 有不同的行为 ;
    多态 通过 方法的 重载 ( Overloading ) 和 虚函数 ( Virtual Function ) 实现 ;
    多态 可以 提高代码的 灵活性 和 可维护性 , 使代码更加易于扩展和修改 ;

许多面向对象的程序设计语言都提供了较好的信息隐藏的手段,例如C++,JAVA。他们通过在类(Class)中,对访问权限进行限制,以公有(Public),私有(Private)等标签规定了一套访问规则(当然,还有protected),从而实现了信息隐藏。

那么,在C语言这样的面向过程的程序设计语言中,我们怎么来封装自己的抽象数据类型呢?
我们知道,C语言提供了struct关键字,可以让我们将一组各种类型的集合打包成一种新的类型。

但是怎么才能隐藏 struct结构体的内部细节 , 防止外界的直接访问和修改呢?这就需要提及:C语言特性的不透明指针

C语言特性:不透明指针

C语言有这样一个特性,它允许我们在给出一个结构体(struct)的定义之前,先声明指向它的指针(Pointer)

下面的代码可以在mingw32-4.5.2编译器中编译通过。

int main (int argc, char * argv[])  
{  
    struct some_struct * p;    /*p是一个指向struct some_struct的指针,但我们并不知道struct some_struct是什么,它都有哪些成员*/  
    return 0;  
}   

该段代码可以顺利地通过编译,说明这样的声明确实是被允许的。然而,当我们继续,进行解引用的时候:

int main (int argc, char * argv[])  
{  
    struct some_struct * p;   /*p是一个指向struct some_struct的指针,但我们并不知道struct some_struct是什么,它都有哪些成员*/  
    p->some_attribute;        /*现在我们对p解引用,希望获得它的some_attribute这个属性*/  
    return 0;  
}  

这时编译器会向我们报错:error: dereferencing pointer to incomplete type (错误:对指向不完整类型的指针进行解引用)

这时,用户看不见struct内部的具体细节了。

注意:在给出一个结构体的定义之前,先声明指向它的指针,但并不代表我没有定义这个结构体,只是定义在了其他的地方(其他的文件)中

利用不透明指针实现“封装”特性

student.h文件

#ifndef _STUDENT_
#define _STUDENT_

typedef struct stu *student_t; /*声明一种新的类型叫做student_t,它是一个指向struct stu的指针*/

student_t new_student(char *name, int age, double grade);
void delete_student(student_t student);
char* get_student_name(student_t student);
int get_student_age(student_t student);


#endif

student.c文件

#include "student.h"
#include <stdlib.h>
#include <string.h>

struct stu   /*定义了结构体struct stu的具体内容*/ 
{
    char name[28];
    int age;
    double grade;
};

student_t new_student(char *name, int age, double grade)
{
    student_t p = malloc(sizeof(struct stu));

    if (p != NULL)
    {
        strcpy(p->name, name);
        p->age = age;
        p->grade = grade;
    }

    return p;
}

void delete_student(student_t student)
{
    if (student!= NULL)
    {
        free(student);
    }
}

int get_student_age(student_t student)
{
    if (student!= NULL)
    {
        return student->age;
    }
    return -1;
}

char* get_student_name(student_t student)
{
    if (student!= NULL)
    {
        return student->name;
    }
    return NULL;
}

main.c文件

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


int main(void)
{
    student_t stu1;
    stu1 = new_student("zhangsan", 18, 0);

    printf("student age: %d\n", get_student_age(stu1));
    printf("student name: %s\n", get_student_name(stu1));
    return 0;
}

运行结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值