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

2024-05-15 16:18

本文主要是介绍Effective C++:条款23:宁以non-member、non-friend替换member函数,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

(一)

有个class来表示网页浏览器:

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

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

class WebBrowser { 
public: void clearChache(); void clearHistory(); void removeCookies(); void clearEverything(); 
};

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

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

那么哪一个比较好呢?是member函数clearEverything()还是non-member函数claseBrower呢。?

越多东西被封装,我们改变那些东西的能力也就越大。对象内的数据。越少代码看到它(访问它),越多的数据可被封装,也就越能自由地改变对象数据,例如改变成员变量的数量,类型等等。

所以答案当然是non-member函数claseBrower!因为它导致了较大的封装性,因为它并不增加“能过访问class内之private成分”的函数数量。这就解释了为什么clearBrowser(一个non_member non-friend函数)比clearEverything(一个member函数)更受欢迎的原因:它导致WebBrowser class有较大的封装性。

但是这里有两件事情要注意下:

第一:这里只适用于non-member non-friend函数。friend函数对class private成员的访问权力和member函数相同,因此两者对封装的冲击也相同。
第二:只因在意封装而让函数“成为class 的non-member”,并不意味着它“不可以是另一个class的member”。假如我们可以另clearBrowser成为某工具类(utility class)的一个static member函数。

(二)

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

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

像clearBrowser这样的函数是个“提供便利的函数”。一个像WebBrowser这样的class可能拥有大量的便利函数,某些与书签有关,某些与打印有关,某些与cookie的管理有关…,通常,大多数客户只对其中某些感兴趣。没有道理一个只对书签感兴趣的客户却与一个cookie相关便利函数发生编译相依关系。分离他们最直接的方法是将他们放入不同的头文件:

//头文件webbrowser.h这一头文件针对class WebBrowser自身以及WebBrowser核心机能。

namespace WebBrowserStuff{ void clearBrowser(WebBrowser wb); ...//WebBrowser核心机能,几乎所有客户都需要的non-member函数。 
}//头文件“webbrowserbookmarks.h”namespace WebBrowserStuff{ class WebBrowser{...}; ...//与书签相关的便利函数 
}//头文件“webbrowsercookies.h”namespace WebBrowserStuff{ class WebBrowser{...}; ...//与cookie相关的便利函数 
}

C++标准程序库正是这样的组织方式。数十个头文件,每个头文件声明std的某些机能。如果只想使用vector不用#include <memory>;如果不想使用list也不需要#include <list>.这允许客户只对他们所用的那一小部分系统形成编译相依。这种切割机能并不适合class成员函数,因为class 必须整体定义,不能被分割为片段。namespace可以跨越多个源码文件,而class不能。

将所有便利函数放在多个头文件中但隶属同一个命名空间,意味着客户可以轻松扩展这一组便利函数。他们所要做的就是添加更多non-member non-friend函数到此命名空间内。例如:如果客户想写些与影像下载相关的便利函数,只要在WebBrowserStuff命名空间内建立一个头文件,内含那些函数的声明即可。新函数就像其他旧函数一样可用且整合为一体。这是class无法提供的另一个性质,因为class定义对客户是不能扩展的。



请记住:

尽量用non-member non-friend函数替换member函数。可以增加封装性、包裹弹性(packaging flexibility)、和机能扩充性。




这篇关于Effective C++:条款23:宁以non-member、non-friend替换member函数的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/992310

相关文章

C++中unordered_set哈希集合的实现

《C++中unordered_set哈希集合的实现》std::unordered_set是C++标准库中的无序关联容器,基于哈希表实现,具有元素唯一性和无序性特点,本文就来详细的介绍一下unorder... 目录一、概述二、头文件与命名空间三、常用方法与示例1. 构造与析构2. 迭代器与遍历3. 容量相关4

C++中悬垂引用(Dangling Reference) 的实现

《C++中悬垂引用(DanglingReference)的实现》C++中的悬垂引用指引用绑定的对象被销毁后引用仍存在的情况,会导致访问无效内存,下面就来详细的介绍一下产生的原因以及如何避免,感兴趣... 目录悬垂引用的产生原因1. 引用绑定到局部变量,变量超出作用域后销毁2. 引用绑定到动态分配的对象,对象

Python函数作用域与闭包举例深度解析

《Python函数作用域与闭包举例深度解析》Python函数的作用域规则和闭包是编程中的关键概念,它们决定了变量的访问和生命周期,:本文主要介绍Python函数作用域与闭包的相关资料,文中通过代码... 目录1. 基础作用域访问示例1:访问全局变量示例2:访问外层函数变量2. 闭包基础示例3:简单闭包示例4

Python中isinstance()函数原理解释及详细用法示例

《Python中isinstance()函数原理解释及详细用法示例》isinstance()是Python内置的一个非常有用的函数,用于检查一个对象是否属于指定的类型或类型元组中的某一个类型,它是Py... 目录python中isinstance()函数原理解释及详细用法指南一、isinstance()函数

python中的高阶函数示例详解

《python中的高阶函数示例详解》在Python中,高阶函数是指接受函数作为参数或返回函数作为结果的函数,下面:本文主要介绍python中高阶函数的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录1.定义2.map函数3.filter函数4.reduce函数5.sorted函数6.自定义高阶函数

Python中的sort方法、sorted函数与lambda表达式及用法详解

《Python中的sort方法、sorted函数与lambda表达式及用法详解》文章对比了Python中list.sort()与sorted()函数的区别,指出sort()原地排序返回None,sor... 目录1. sort()方法1.1 sort()方法1.2 基本语法和参数A. reverse参数B.

C++读写word文档(.docx)DuckX库的使用详解

《C++读写word文档(.docx)DuckX库的使用详解》DuckX是C++库,用于创建/编辑.docx文件,支持读取文档、添加段落/片段、编辑表格,解决中文乱码需更改编码方案,进阶功能含文本替换... 目录一、基本用法1. 读取文档3. 添加段落4. 添加片段3. 编辑表格二、进阶用法1. 文本替换2

C++中处理文本数据char与string的终极对比指南

《C++中处理文本数据char与string的终极对比指南》在C++编程中char和string是两种用于处理字符数据的类型,但它们在使用方式和功能上有显著的不同,:本文主要介绍C++中处理文本数... 目录1. 基本定义与本质2. 内存管理3. 操作与功能4. 性能特点5. 使用场景6. 相互转换核心区别

Python进行word模板内容替换的实现示例

《Python进行word模板内容替换的实现示例》本文介绍了使用Python自动化处理Word模板文档的常用方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友... 目录技术背景与需求场景核心工具库介绍1.获取你的word模板内容2.正常文本内容的替换3.表格内容的

MySQL批量替换数据库字符集的实用方法(附详细代码)

《MySQL批量替换数据库字符集的实用方法(附详细代码)》当需要修改数据库编码和字符集时,通常需要对其下属的所有表及表中所有字段进行修改,下面:本文主要介绍MySQL批量替换数据库字符集的实用方法... 目录前言为什么要批量修改字符集?整体脚本脚本逻辑解析1. 设置目标参数2. 生成修改表默认字符集的语句3