前言

众所周知,封装、继承和多态是面向对象编程的三大特性。C++作为一门面向对象的编程语言,自然支持了这些特性,但C++是如何实现这些特性的呢?今天先说下我理解的封装。

封装

通常我们会把下面的行为也叫封装,但面向对象的封装并不只是把函数或类型包裹在一起,更重要的是给这些函数或类型设置访问权限。

  • 将一堆类型变量用一个结构体包裹起来,对外只有一个结构体名
  • 将一堆过程用一个函数包裹起来,对外只有一个函数名

C++提供了三种权限

  • public:任何类都能可访问
  • protected:只有本类或本类的派生类能访问
  • private:只有本类能访问

    类指class和struct,并不单指class。class和struct只有默认访问权限的区别
    友元类和友元函数能访问该类的任何东西

访问权限只在编译阶段检查,而且检查的依据只是当前的类声明,举个例子来说明

  • 执行g++ student.cpp -fPIC -shared -o liba.so将以下代码编译为动态库,提供给其他人使用。
// student.h
class Student
{
public:
    Student();
private:
    int age;
};

// student.cpp
#include "student.h"
Student::Student()
{
    age = 10;
}
  • 篡改student.h,将所有成员变量的访问权限都设为public
class Student
{
public:
    Student();
    int age;
};
  • g++ main.cpp -L./ -la编译没有报错。——从此就可以看出“权限检查的依据只是当前的类声明”
// main.cpp
#include "student.h"
int main()
{
    Student s;
    s.age = 40; // 肆意变更自己的年纪
    return 0;
}

当然可以采用如下的方式来隐藏内部成员变量细节,这样即使调用者修改了类声明里的访问权限,也不知道为了来达到自己的目的该如何修改。

// student.h
class Student
{
public:
    Student();
private:
    struct Internal;
    Internal* in;
};

此外,这还带来一个好处就是内部成员变量的修改,调用者完全无感知,不需要更新头文件了(我想这才是使用这种方式的主要原因)。当然这仍然无法阻止别人猜测出数据结构后,直接使用成员变量地址去读写。个人觉得只有提供给第三方或第二方的类才需要使用这种方式(内部还是可以信任的)。如果所有类都这样实现的话,可能就会导致内存碎片了。

结语

我觉得封装最大的意义还是在于让调用者不要关注自己无权访问的内容(忽略细节),只需要基于自己可访问的部分(基于接口)去实现业务。C是一门面向过程的语言,它是没有访问权限这一说的,调用者无法知道哪些是自己无权访问的,编译器也无法提醒越权访问的错误,C++则提供了这种编程约束。

C++系列总结——封装的更多相关文章

  1. 架构漫谈系列(2) 封装(Encapsulation)

    这是这个系列的第二篇.在第二篇里,我决定讲一讲封装. 程序的不同部分应该用封装去互相隔离,模块之间应该不应该产生很随意的关联. 可能有的人觉得不解,又或觉得是有道理的废话,不急,先一步一步来. 我们先 ...

  2. 3-STM32带你入坑系列(自己封装点亮一个灯的库--Keil)

    2-STM32带你入坑系列(点亮一个灯--Keil) 首先建一个stm32f103x.h的文件,然后 #include "stm32f103x.h" 还记得上一节 现在呢就是做一个 ...

  3. jQuery组件系列:封装标签页(Tabs)

    我自己封装的组件,你也行,静态链接地址 http://www.cnblogs.com/leee/p/5190489.html 声明.最好,先把代码拷过去运行一下,其实特别丑~再往下看 我没优化,因为我 ...

  4. <数据结构系列1>封装自己的数组——手写动态泛型数组(简化版ArrayList)

    哈哈,距离上一次写博客已经快过去半个月了,这这这,好像有点慢啊,话不多说,开始我们的手写动态泛型数组 首先是我们自己写一个自己的动态数组类,代码如下所示: public class Array< ...

  5. javascript设计模式系列二-封装

    JavaScript封装: var Book = function (id, name, price) { this.id = id, this.name = name, this.price = p ...

  6. JS组件系列——自己封装一个上传文件组件

    页面调用: $('#fileUpload').cemsUpload({ errorEmpty:'<s:text name="cupgrade.view.tip.upload.file. ...

  7. 测试平台系列(80) 封装Redis客户端

    大家好~我是米洛! 我正在从0到1打造一个开源的接口测试平台, 也在编写一套与之对应的完整教程,希望大家多多支持. 欢迎关注我的公众号测试开发坑货,获取最新文章教程! 回顾 上一节我们编写了Redis ...

  8. openssl之EVP系列之1---算法封装

    openssl之EVP系列之1---算法封装     ---依据openssl doc/crypto/EVP.pod翻译和自己的理解写成     (作者:DragonKing, Mail: wzhah ...

  9. 封装的多功能多效果的RecyclerView

    开源界有一句很有名的话叫"不要重复发明轮子",当然,我今天的观点不是要反驳这句话,轮子理论给我们的开发带来了极大的便利,.但我想说的是,既要会用轮子,也要知道轮子怎么造,必要的时候 ...

随机推荐

  1. LVS的DR模型配置

    LVS的DR模型配置 介绍 下图为DR模型的通信过程,图中的IP不要被扑结构中的IP迷惑,图里只是为了说明DR的通信原理,应用到本例中的拓扑上其工作原理不变. 拓扑结构 服务器 IP地址 角色 Srv ...

  2. C#处理json实战

    昨天看到技术群中发了一个查询天气的api,http://www.sojson.com/open/api/weather/json.shtml?city=南昌 点进去看,发现服务器传回来一个天气信息的j ...

  3. c# 事件的订阅发布Demo

    delegate void del(); class MyClass1 { public event del eventcount;//创建事件并发布 public void Count() { ; ...

  4. ArcGIS JavaScript API4.8 底图选择的几种方案

    创建一个HTML页面,引入ArcGIS JavaScript API,在<body>标签内创建一个div并添加ID值,在<head>标签内设置样式<style>,在 ...

  5. 织梦5.7sp1最新问题:后台不显示编辑器

    1.在后台的“系统基本参数”里修改“站点设置”的“网页主页链接:空”. 2.修改“核心设置”DedeCMS安装目录:空“. 3.试试,问题解决.

  6. winform 实现类似于TrackBar的自定义滑动条,功能更全

    功能很全,随便列几个 1.可以设置滑块的大小,边框颜色.背景色.形状等等吧 2.可以设置轨道的方向.边框颜色.背景色.阴影等等 ... 效果图: 下载链接https://download.csdn.n ...

  7. C++ 最简单的日志类

    最近搞一个 C++ 项目的二次开发,没玩过 C++,可谓步履维艰.自己写个简单的日志类都被各种坑折磨.终于搞定了. 参考了这篇博客,并且进一步简化:https://www.cnblogs.com/Ds ...

  8. 探究 CSS 混合模式\滤镜导致 CSS 3D 失效问题

    今天在写一个小的 CSS Demo,一个关于 3d 球的旋转动画,关于 CSS 3D,少不了会使用下面这几个属性: { transform-style: preserve-3d; perspectiv ...

  9. Cocos Creator 资源加载流程剖析【二】——Download部分

    Download流程的处理由Downloader这个pipe负责(downloader.js),Downloader提供了各种资源的"下载"方式--即如何获取文件内容,有从网络获取 ...

  10. GROUP BY你都不会!ROLLUP,CUBE,GROUPPING详解

    Group By Group By 谁不会啊?这不是最简单的吗?越是简单的东西,我们越会忽略掉他,因为我们不愿意再去深入了解它. 1 小时 SQL 极速入门(一) 1 小时 SQL 极速入门(二) 1 ...