IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C 封装与抽象 面向对象编程 -> 正文阅读

[C++知识库]C 封装与抽象 面向对象编程

封装与抽象

封装性是面向对象编程的三大特性(封装性、继承性、多态性)之一,但也是最重要的特性。封装+抽象相结合就可以对外提供一个低耦合的模块。

数据封装是一种把数据和操作数据的函数捆绑在一起的机制,数据抽象是一种仅向用户暴露接口而把具体的实现细节隐藏起来的机制。

在C语言中,数据封装可以从结构体入手,结构体里可以放数据成员和操作数据的函数指针成员。当然,结构体里也可以只包含着要操作的数据。

下面以一个简单的实例作为演示。

设计一个软件模块,模块中要操作的对象是长方形,需要对外提供的接口有:

1、创建长方形对象;
2、设置长、宽;
3、获取长方形面积;
4、打印长方形的信息(长、宽、高);
5、删除长方形对象。

下面我们来一起完成这个demo代码。首先,我们思考一下,我们的接口命名大概是怎样的?其实这是有规律可循的,我们看RT-Thread的面向对象接口是怎么设计的
在这里插入图片描述

在这里插入图片描述

我们也模仿这样子的命名形式来给我们这个demo的几个接口命名:

1、shape_create
2、shape_set
3、shape_getArea
4、shape_display
5、shape_delete

我们建立一个rect.h的头文件,在这里声明我们对外提供的几个接口。这时候我们头文件可以设计为:

typedef struct _fun_ptr
{
    int (*area)(void);
}fun_ptr;

typedef struct _Shape
{
    char* object_name;
    int length;
    int width;
    fun_ptr fptr;
}Shape, *pShape;

/* 对象操作 */
HandleShape shape_create(const char* object_name);
void shape_set(HandleShape shape, int length, int width);
int shape_getArea(HandleShape shape);
void shape_display(HandleShape shape);
void shape_delete(HandleShape shape);

这样做是没有什么问题的。可是数据隐藏得不够好,我们提供给外部用的东西要尽量简单。
我们可以思考一下,对于C语言的文件操作,C语言库给我们提供怎么样的文件操作接口?如:

FILE *fopen(const char *pathname, const char *mode);
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

我们会创建一个文件句柄(描述符),然后之后只要操作这个文件句柄就可以,我们不用关心FILE具体是怎么实现的。

什么是句柄?看一下百度百科的解释:
在这里插入图片描述

我们也可以创建我们的对象句柄,对外提供的头文件中只需暴露我们的对象句柄,不用暴露具体的实现。以上头文件rect.h代码可以修改为:

#ifndef __SHAPE_H
#define __SHAPE_H

#ifdef __cplusplus
extern "C" {
#endif

/* 对象句柄 */
typedef void* HandleShape;

/* 对象操作 */
HandleShape shape_create(const char* object_name);
void shape_set(HandleShape shape, int length, int width);
int shape_getArea(HandleShape shape);
void shape_display(HandleShape shape);
void shape_delete(HandleShape shape);

#ifdef __cplusplus
}
#endif

#endif

这里用到了void*,其为无类型指针,void *可以指向任何类型的数据。然后具体要操作怎么样的结构体可以在.c中实现:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "CShape.h"

typedef struct _fun_ptr
{
    int (*area)(void);
}fun_ptr;

typedef struct _Shape
{
    char* object_name;
    int length;
    int width;
    fun_ptr fptr;
}Shape, *pShape;

下面我们依次实现上述五个函数:

HandleShape shape_create(const char* object_name)
{
    printf(">>>>>>>>>> %s: %s (line: %d) <<<<<<<<<<\n", __FILE__, __FUNCTION__, __LINE__);
    /* 给shape结构体变量分配内存 */
    pShape shape = (pShape)malloc(sizeof(Shape));
    if (NULL == shape)
    {
        printf("shape memory malloc failed!\n");
        abort();
    }
    /* 给shape->object_name字符串申请内存 */
    shape->object_name = (char*)malloc(strlen(object_name) + 1);
    if (NULL == shape->object_name)
    {
        printf("shape->object_name memory malloc failed!\n");
        abort();
    }

    /* 给结构体各成员进行初始化 */
    strncpy(shape->object_name, object_name, strlen(object_name) + 1);
    shape->length = 0;
    shape->width = 0;
    
    return ((HandleShape)shape);
}

void shape_set(HandleShape shape, int length, int width)
{
    printf(">>>>>>>>>> %s: %s (line: %d) <<<<<<<<<<\n", __FILE__, __FUNCTION__, __LINE__);
    if (shape)
    {
        ((pShape)shape)->length = length;
        ((pShape)shape)->width = width;
    }
}

int shape_getArea(HandleShape shape)
{
    return ( ((pShape)shape)->length * ((pShape)shape)->width );
}

void shape_display(HandleShape shape)
{
    printf(">>>>>>>>>> %s: %s (line: %d) <<<<<<<<<<\n", __FILE__, __FUNCTION__, __LINE__);
    if (shape)
    {
        printf("object_name = %s\n", ((pShape)shape)->object_name);
        printf("length = %d\n", ((pShape)shape)->length);
        printf("width = %d\n", ((pShape)shape)->width);
        printf("area = %d\n", shape_getArea(shape));
    }
}

void shape_delete(HandleShape shape)
{
    printf(">>>>>>>>>> %s: %s (line: %d) <<<<<<<<<<\n", __FILE__, __FUNCTION__, __LINE__);
    if (shape)
    {
        // free(((HandleShape)shape)->object_name);
        // ((HandleShape)shape)->object_name = NULL;
        // free(shape);
        // shape = NULL;
    }
}
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-01-08 13:48:12  更:2022-01-08 13:49:33 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 11:28:56-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码