宁以non-member、non-friend替换member函数——条款23

Effective C++ 详解条款23:宁以non-member、non-friend替换member函数 总结: 宁可拿non-member non-friend函数替换member 函数。这样做可以增加封装性、包裹弹性(packaging flexibility)和机能扩充性。 举例:一个class用来表示网页浏览器。这样的class可能提供的众多函数中,有一些用来清除下载元素高速缓存区、清除访问过的URLS的历史记录、以及移除系统中的所有cookies: class webBrowser { public: ... void clearCache( ); void clearHisto 阅读详情

        想象有个class用来表示网页浏览器。这样的class可能提供的众多函数中,有一些用来消除下载元素高速缓存区(cache of download elements)、清除访问过的URLs的历史记录(history of visited URLs)、以及移除系统中的所有cookies:

class WebBrowser {
public:
	...
	void clearCache();
	void clearHistory();
	void removeCookies();
	...
};

        许多用户会想一整个执行所有这些动作,因此WebBrowser也提供一个这样一个函数:

class WebBrowser {
public:
	...
	void clearEverything(); // 调用clearCache,clearHistory和removeCookies
	
	
	...
};

        当然,这一机能也可由一个non-member函数调用适当的member函数而提供出来:

void clearBrowser(WebBrowser& wb)
{
	wb.clearCache();
	wb.clearHistory();
	wb.removeCookies();
}

        那么,哪一个比较好呢?是member函数clearEverything还是non-member函数clearBrowser?

        面向对象守则要求,数据以及操作数据的那些函数应该被捆绑在一块,这意味它建议member函数是较好的选择。不幸的是这个建议不正确。这是基于对面向对象真实意义的一个误解。面向对象守则要求数据应该尽可能被封装,然而与直观相反地,member函数clearEverything带来的封装性比non-member函数clearBrowser低。此外,提供non-member函数可允许对WebBrowser相关机能有较大的包裹弹性(packaging flexibility),而那最终导致较低的编译相依度,增加WebBrowser的可延伸性。因此在许多方面non-member做法比member做法好。重要的是,我们必须了解其原因。

        让我们从封装开始讨论。如果某些东西被封装,它就不在可见。愈多东西被封装,愈少人可以看到它。而愈少人看到它,我们就有愈大的弹性去变化它,因为我们的改变仅仅直接影响看到改变的那些人事物。因此,愈多东西被封装,我们改变那些东西的能力也就愈大。这就是我们首先推崇封装的原因:它使我们能够改变事物而只影响有限客户。

        现在考虑对象内的数据。愈少代码可以看到数据(也就是访问它),愈多的数据可被封装,而我们也就愈能自由地改变对象数据,例如改变成员变量的数量、类型等等。如何测量“有多少代码可以看到某一块数据”呢?我们计算能够访问该数据的函数数量,作为一种粗糙的量测。愈多函数可访问它,数据的封装性就愈低。

        条款22曾说过,成员变量应该是private,因为如果它们不是,就有无限量的函数可以访问它们,它们也就毫无封装性。能够访问private成员变量的函数只有class的member函数加上friend函数而已。这就解释为什么clearBrowser(一个non-member、non-friend函数)比clearEverything(一个member函数)更受欢迎的原因:它导致WebBrowser class有较大的封装性。

        在这一点上有两件事情值得注意:

        第一,这个论述只适用于non-member、non-friend函数。friend函数对class private成员的访问权力和member函数相同,因此两者对封装的冲击力道也相同。从封装角度看,这里的选择关键并不在member和non-member函数之间,而是在member和non-member、non-friend函数之间。(当然,封装并非唯一考虑。条款24解释当我们考虑隐式类型转换,应该在member和non-member函数之间抉择。)

        第二件值得注意的事情是,只因在意封装性而让函数“成为class的non-member”,并不意味它“不可以是另一个class的member”。例如我们可以令clearBrowser成为某工具类(utility class)的一个static member函数。只要它不是WebBrowser的一部分(或成为其friend),就不会影响WebBrowser的private成员封装性。

        在C++,比较自然的做法是让clearBrowser成为一个non-member函数并且位于WebBrowser所在的同一个namespace(命名空间)内:

namespace WebBrowserStuff {
	class WebBrowser {...};
	void clearBrowser(WebBrowser& wb);
	...
}

      然而这不只是为了看起来自然而已,要知道,namespace和class不同,前者可跨越多个源码文件,而后者不能。这很重要,一个像WebBrowser这样的class可能拥有大量便利函数,分离它们的最直接做法就是将书签相关便利函数声明于一个头文件,将cookie相关便利函数声明于另一个头文件,再将打印相关便利函数声明于第三个头文件,以此类推:

// 头文件“webbrowser.h”——这个头文件针对class WebBrowser自身以及WebBrowser核心机能。
namespace WebBrowserStuff {
	class WebBrowser {...};
	...               // 核心机能,例如几乎所有客户都需要的non-member函数。
}
// 头文件“webbrowserbookmarks.h”
namespace WebBrowserStuff {
	...               // 与书签相关的便利函数。
}
// 头文件“webbrowsercookies.h”
namespace WebBrowserStuff {
	...               // 与cookie相关的便利函数。
}
...

        将所有便利函数放在多个头文件内,但隶属于同一个命名空间,意味客户可以轻松扩展这一组便利函数。他们需要做的就是添加更多non-member、non-friend函数到此命名空间内。举个例子,如果某个WebBrowser客户决定写些与影像下载相关的便利函数,他只需要在WebBrowserStuff命名空间内建立一个头文件,内含那些函数的声明即可。新函数就像其它旧有的便利函数那样可用且整合为一体。这是class无法提供的另一个性质,因为class定义式对客户而言是不能扩展的。当然,客户可以派生出新的classes,但derived classes无法访问base class中被封装的(即private)成员,于是如此的“扩展机能”拥有的只是次级身份。此外——如条款7所说,并非所有classes都被设计用来作为base classes。

请记住

  • 宁可拿non-member、non-friend函数替换member函数。这样做可以增加封装性、包裹弹性(packaging flexibility)和机能扩充性。
利用SPSS实现逻辑回归,树模型,以及广义线性模型 本案例是IBM SPSS数据分析与挖掘实战案例精粹----第九章的学习记录 案例背景:分析出导致急救后迟发性颅脑损伤的主要影响因素,共有201项案例: 分析思路:先使用logistic回归模型进行影响因素筛选,然后利用分类树探索自变量中是否存在交互作用,最后利用广义线性模型过程拟合带交互项的Logistic回归模型 字段:性别,年龄,收缩压,舒张压,血小板,脑挫伤,中线位移,脑肿胀,入院意识,是否手术急救,其余急救措施,是否出现迟发性脑损伤; ... 阅读详情

相关推荐

Pytorch的一小步,昇腾芯片的一大步

相信在AI圈的人多多少少都看到了最近的信息:PyTorch最新2.1版本宣布支持华为昇腾芯片!

机器学习-深度学习-图像处理-opencv-段子 5239

Effective C++学习---04.设计与声明

理想上,如果客户企图使用某个接口而却没有获得他所预期的行为,这个代码不该通过编译;如果代码通过了编译,它的行为就该是客户所想要的。

weixin_43614932的博客 740

Jetson AGX ORIN硬件初始化和环境部署

orin预安装了ubuntu20.04,只需开机,像重装系统一样设置用户信息即可,可以参考官网的教程[https://developer.nvidia.com/embedded/learn/get-started-jetson-agx-orin-devkit],官网提供了两种方式:一种是orin + 显示器,orin有提供DP接口,你需要准备一台显示器,最好也是有DP口的,因为我用DP转HDMI的连的,分辨率会受影响。确认安装的路径,一般直接回车安装在默认的 /home/你的名字/anaconda3。

TracyGC的博客 3831

C/C++编程:宁以non-member、non-friend替换member函数

引入 想象有个类用来表示网页浏览器。这样的类可能提供的众多函数中,有一些用来清除下载元素高速缓冲器、清除访问过的URLs的历史记录,以及移除系统中的所有cookies: class WebBrower{ public: void clearCache(); void clearHistory(); void removeCookies(); }; 很多用户想一整个执行所有的这些动作,因此webBrowser也提供这样一个函数: class WebBrower{ public: void clear

OceanStar的博客 1675

JSP期末考试复习习题及答案

以下习题是对于平时课堂小测的整理,如有错误敬请指正! 欢迎一起交流~ 预祝各位小伙伴们考试顺利! Test1 一. 单选题 – 1.(单选题)当用户请求jsp页面时,JSP引擎就会执行该页面的字节码文件响应客户的请求,执行字节码文件的结果是() A. 发送一个JSP源文件到客户端 B. 发送一个Java文件到客户端 C. 发送一个HTML页面到客户端 D. 什么都不做 – 2.(单选题)下列动态网页和静态网页的根本区别描述错误的是( D) A. 静态网页服务器端返回的HTML文件是事先存储好的 B. 动.

技术小白 2万+

快速配置ORCAD导出智能PDF原理图

在OrCAD 中导出类似Altium Designer的智能PDF(即交互式PDF);

QingNing3028的博客 3940

条款 23 :宁以non-member,non-friend替换member函数

条款 23 :宁以non-member,non-friend替换member函数 Perfer non-member non-friend functions to member functions. 越多东西被封装,我们改变那些东西的能力也就越大。这就是我们推崇封装的原因:他使我们能够改变事物而只影响有限客户。 导致较大的封装性的是non-member,non-friend函数,因为他们并不增加 能够访问class内private数据成分的函数数量。 //假设我们有一个类来表示网页浏览器 //这样

weixin_45730130的博客 213

风力发电机缺陷检测平台

风力发电机缺陷检测平台相关内容展示

weixin_39779415的博客 1111

Effective C++ 规则23:宁以non-member、non-firend替换member函数

C++

一个小孩 251

用Obsidian搭建个人知识库:AI时代如何构建你的第二大脑

AI 时代,真正有价值的不只是获取知识,而是沉淀属于自己的知识体系。本文从 Obsidian 安装、目录设计、双向链接、插件推荐到 AI 联动、多端同步,手把手教你打造高效、可持续进化的个人知识库,让知识真正为你所用。🧠

XiaoqiangClub的博客 462

基于Simulink的发动机管理系统中的自适应增压控制系统设计

通过上述详细设计步骤,我们成功开发了一个基于Simulink的自适应增压控制系统。该系统不仅能够实时监测和预测发动机的运行状态,动态调整增压压力目标值,还具备实时监控、故障诊断和保护功能,确保系统的安全性和可靠性。此外,通过仿真实验和硬件在环测试,我们验证了系统的性能,并对其进行了优化,使其能够更好地满足实际应用需求。这个项目展示了如何利用MATLAB/Simulink的强大功能,结合控制理论和工程实践,开发出高效、可靠的自适应增压控制系统。

MHD0815的博客 219

Effective C++之条款23:宁以non-member、non-friend替换member函数

声明: 文中内容收集整理自《Effective C++(中文版)第三版》,版权归原书所有。 本内容在作者现有能力的基础上有所删减,另加入部分作者自己的理解,有纰漏之处敬请指正。 条款23:宁以non-member、non-friend替换member函数 Prefer non-member non-friendfunctionsto member functions. 本条款讨论的还是封...

HakunaMatata的博客 328

opencv案例实战——银行卡模式匹配识别

在之前的几篇文章中我们已经介绍了opencv的一些基础知识,本篇文章我们将结合一个案例运用之前的知识并且学习opencv中模式匹配的应用,用到的知识点如果有不清楚的可以查看上面列出来的系列文章。具体代码会放在最后。

艾醒的博客 1337

Effective C++ 条款 23:宁以 non-member、non-friend 替换 member 函数

【代码】Effective C++ 条款 23:宁以 non-member、non-friend 替换 member 函数。

weixin_42255569的博客 336

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Effective C++ 条款23:宁以 non-member、non-friend 替换 member 函数

探索 C++ 封装性最大化的设计哲学,理解为何 non-member non-friend 函数往往优于 member 函数

凡人叶枫的博客 218

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

【复读EffectiveC++23】条款23:宁以 non-member、non-friend替换member函数

宁可拿非成员 非友元函数替换成员函数。这样做可以增加封装性、包裹弹性和机能扩充性。

weixin_51122602的博客 1076

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

Effective C++条款23:宁以 non-member、non-friend替换member函数

Effective C++条款23:宁以 non-member、non-friend替换member函数(Prefer non-member non-friend functions to member functions)

CltCj的博客 492

条款23:宁以 non-member、non-friend 替换 member 函数

Effective C++之条款23

weixin_43739503的博客 204

[Effective C++]条款23:宁以non-member、non-friend替换member函数

这个原则的核心思想是,如果一个函数不需要直接访问类的私有或受保护成员,那么它应该被设计为非成员函数(non-member function),而不是成员函数(member function)在C++中,宁以非成员函数、非友元函数替换成员函数,的设计原则是为了增强封装性、减少类之间的耦合,并提高代码的灵活性和可维护性。有一个坐标点类Point,现在需要实现一个函数来计算两个点的距离。

Tim_10的博客 424

Effective C++ 条款23_宁以 non-member、non-friend 替换 member 函数_不止于此

Prefer non-member non-friend functions to member functions 想象有个 class 用来表示网页浏览器。这样的 class 可能提供的众多函数中,有一些用来清除下载元素高速缓存区(cache of download elements)、清除访问过的 URLs 的历史记录(history of visited URLs)、以及移除系统中的所有cookies: class WebBrowser{ public: ... void clearCache(

嘟嘟的博客 238

EffectiveC++-条款23:宁以 non-member、non-friend 替换 member函数

## 一. 内容 1. 举个例子,当你有个class表示浏览器时,有众多功能需要提供,其中可能有清除下载元素的高速缓存区,清除访问过的URLs,清除系统中所有的cookies。 示例代码 ```cpp class WebBrowser { public: void ClearCache(){std::cout............

MoOtA 286

Effective C++条款23:宁以non-member、not-friend替换member函数

假如有一个以下的类,用来表示网页浏览器,其中有一些函数用来清除下载元素高速缓冲区、清楚访问过的URLs的历史记录、以及移除系统中的所有cookies: class WebBroswer { public: ... void clearCache(); void clearHistory(); void removeCookies(); ... }; 许多用户想一次性执行所有这些动作,因...

qq_44800780的博客 203

Effective C++:条款23:宁以non-member、non-friend替换member函数

(一) 有个class来表示网页浏览器: class WebBrowser { public: void clearChache(); void clearHistory(); void removeCookies(); }; 很多用户会想一整个运行全部这些动作,因此W...

weixin_30914981的博客 107

Effective C++条款23——宁以non-member、non-friend替换member函数(设计与声明)

如果要你在一个member函数(它不只可以访问class内的private数据,也可以取用private函数、enums、 typedefs等等)和一一个non-member,non-friend函数(它无法访问.上述任何东西)之间做抉择,而且两者提供相同机能,那么,导致较大封装性的是non-member non-friend函数,因为它并不增加“能够访问class内之private成分”的函数数量。面向对象守则要求,数据以及操作数据的那些函数应该被捆绑在一块,这意味它建议member函数是较好的选择。

StudyWinter的博客 575

读书笔记《Effective C++》条款23:宁以non-member、non-friend替换member函数

先看个例子,想象有个class用来表示网页浏览器。这样的class可能提供的众多函数中,有一些用来清楚下载元素告诉缓存区、清楚访问过的URLs的历史记录、以及移除系统中的所有cookies: class WebBrowser { public: void clearCache(); void clearHistory(); void removeC

Do-Program的专栏 296
上一篇: 将成员变量声明为private——条款22
下一篇: 若所有参数皆需类型转换,请为此采用non-member函数——条款24
OODeveloper
博客等级 码龄12年 43粉丝 137原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值