C++系列总结——封装
前言
众所周知,封装、继承和多态是面向对象编程的三大特性。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++系列总结——封装的更多相关文章
- 架构漫谈系列(2) 封装(Encapsulation)
		这是这个系列的第二篇.在第二篇里,我决定讲一讲封装. 程序的不同部分应该用封装去互相隔离,模块之间应该不应该产生很随意的关联. 可能有的人觉得不解,又或觉得是有道理的废话,不急,先一步一步来. 我们先 ... 
- 3-STM32带你入坑系列(自己封装点亮一个灯的库--Keil)
		2-STM32带你入坑系列(点亮一个灯--Keil) 首先建一个stm32f103x.h的文件,然后 #include "stm32f103x.h" 还记得上一节 现在呢就是做一个 ... 
- jQuery组件系列:封装标签页(Tabs)
		我自己封装的组件,你也行,静态链接地址 http://www.cnblogs.com/leee/p/5190489.html 声明.最好,先把代码拷过去运行一下,其实特别丑~再往下看 我没优化,因为我 ... 
- <数据结构系列1>封装自己的数组——手写动态泛型数组(简化版ArrayList)
		哈哈,距离上一次写博客已经快过去半个月了,这这这,好像有点慢啊,话不多说,开始我们的手写动态泛型数组 首先是我们自己写一个自己的动态数组类,代码如下所示: public class Array< ... 
- javascript设计模式系列二-封装
		JavaScript封装: var Book = function (id, name, price) { this.id = id, this.name = name, this.price = p ... 
- JS组件系列——自己封装一个上传文件组件
		页面调用: $('#fileUpload').cemsUpload({ errorEmpty:'<s:text name="cupgrade.view.tip.upload.file. ... 
- 测试平台系列(80) 封装Redis客户端
		大家好~我是米洛! 我正在从0到1打造一个开源的接口测试平台, 也在编写一套与之对应的完整教程,希望大家多多支持. 欢迎关注我的公众号测试开发坑货,获取最新文章教程! 回顾 上一节我们编写了Redis ... 
- openssl之EVP系列之1---算法封装
		openssl之EVP系列之1---算法封装 ---依据openssl doc/crypto/EVP.pod翻译和自己的理解写成 (作者:DragonKing, Mail: wzhah ... 
- 封装的多功能多效果的RecyclerView
		开源界有一句很有名的话叫"不要重复发明轮子",当然,我今天的观点不是要反驳这句话,轮子理论给我们的开发带来了极大的便利,.但我想说的是,既要会用轮子,也要知道轮子怎么造,必要的时候 ... 
随机推荐
- javascript深入理解-从作用域链理解闭包
			一.概要 红宝书(P178)对于闭包的定义:闭包就是有权访问另外一个函数作用域中变量的函数. MDN,对于闭包的定义:闭包就是指能够访问自由变量的函数. 那么什么是自由变量?自由变量就是在函数中使用, ... 
- redis基本类型以及优点特性
			1.什么是redis? redis是一个基于内存的高性能key-value数据库 2.redis基本数据类型及应用场景 支持多种数据类型: string(字符串) String数据结构是简单的k ... 
- Python爬虫入门教程 56-100 python爬虫高级技术之验证码篇2-开放平台OCR技术
			今日的验证码之旅 今天你要学习的验证码采用通过第三方AI平台开放的OCR接口实现,OCR文字识别技术目前已经比较成熟了,而且第三方比较多,今天采用的是百度的. 注册百度AI平台 官方网址:http:/ ... 
- 整合X-Admin前端框架改造ABP
			“站在巨人的肩膀上”,这样一来,不要万事亲恭,在值得的方向上节约时间,毕竟人生就这么一次.在接触ABP以来,一直想花点时间整合LayUI前端框架到ABP中,进而能够逐渐打磨出一套适合自己的框架,开发习 ... 
- redis的bigkey扫描脚本
			众所周知,redis里面的大key存在是非常危险的一件事情.因为最近的工作转移到中间件相关的工作,因此关注了一下bigkey的扫描方法.首先介绍一下阿里云提供的扫描脚本: 具体可见:https://y ... 
- 一文搞懂RAM、ROM、SDRAM、DRAM、DDR、flash等存储介质
			一文搞懂RAM.ROM.SDRAM.DRAM.DDR.flash等存储介质 存储介质基本分类:ROM和RAM RAM:随机访问存储器(Random Access Memory),易失性.是与CPU直接 ... 
- ASP.NET Aries 高级开发教程:Excel导入之代码编写(番外篇)
			前言: 以许框架提供的导入配置功能,已经能解决95%以上的导入情况,但有些情况总归还是得代码来解决. 本篇介绍与导入相关的代码. 1.前端追加导入时Post的参数: var grid = new AR ... 
- Java线程监控及中断
			我们系统中经常有耗费时间长的任务,但客户端往往需要马上得到回应.这时我们就可以如下步骤实现: 1.客户端发起请求执行任务(选定条件,下载报表): 2.首先将任务ID及开始时间,起始状态记录到数据库表中 ... 
- 微擎where范围查询in
			where sale_time in($todayStart,$todayEnd) 
- python列表的交、并、差集
			#!/usr/bin/env python3 l1 = ['] l2 = ['] # 交集 result1 = [i for i in l1 if i in l2] result2 = list(se ... 
