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

相关文章

MySQL常用字符串函数示例和场景介绍

《MySQL常用字符串函数示例和场景介绍》MySQL提供了丰富的字符串函数帮助我们高效地对字符串进行处理、转换和分析,本文我将全面且深入地介绍MySQL常用的字符串函数,并结合具体示例和场景,帮你熟练... 目录一、字符串函数概述1.1 字符串函数的作用1.2 字符串函数分类二、字符串长度与统计函数2.1

python使用try函数详解

《python使用try函数详解》Pythontry语句用于异常处理,支持捕获特定/多种异常、else/final子句确保资源释放,结合with语句自动清理,可自定义异常及嵌套结构,灵活应对错误场景... 目录try 函数的基本语法捕获特定异常捕获多个异常使用 else 子句使用 finally 子句捕获所

C++11范围for初始化列表auto decltype详解

《C++11范围for初始化列表autodecltype详解》C++11引入auto类型推导、decltype类型推断、统一列表初始化、范围for循环及智能指针,提升代码简洁性、类型安全与资源管理效... 目录C++11新特性1. 自动类型推导auto1.1 基本语法2. decltype3. 列表初始化3

C++11右值引用与Lambda表达式的使用

《C++11右值引用与Lambda表达式的使用》C++11引入右值引用,实现移动语义提升性能,支持资源转移与完美转发;同时引入Lambda表达式,简化匿名函数定义,通过捕获列表和参数列表灵活处理变量... 目录C++11新特性右值引用和移动语义左值 / 右值常见的左值和右值移动语义移动构造函数移动复制运算符

C++中detach的作用、使用场景及注意事项

《C++中detach的作用、使用场景及注意事项》关于C++中的detach,它主要涉及多线程编程中的线程管理,理解detach的作用、使用场景以及注意事项,对于写出高效、安全的多线程程序至关重要,下... 目录一、什么是join()?它的作用是什么?类比一下:二、join()的作用总结三、join()怎么

linux批量替换文件内容的实现方式

《linux批量替换文件内容的实现方式》本文总结了Linux中批量替换文件内容的几种方法,包括使用sed替换文件夹内所有文件、单个文件内容及逐行字符串,强调使用反引号和绝对路径,并分享个人经验供参考... 目录一、linux批量替换文件内容 二、替换文件内所有匹配的字符串 三、替换每一行中全部str1为st

postgresql使用UUID函数的方法

《postgresql使用UUID函数的方法》本文给大家介绍postgresql使用UUID函数的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录PostgreSQL有两种生成uuid的方法。可以先通过sql查看是否已安装扩展函数,和可以安装的扩展函数

MySQL字符串常用函数详解

《MySQL字符串常用函数详解》本文给大家介绍MySQL字符串常用函数,本文结合实例代码给大家介绍的非常详细,对大家学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录mysql字符串常用函数一、获取二、大小写转换三、拼接四、截取五、比较、反转、替换六、去空白、填充MySQL字符串常用函数一、

C++中全局变量和局部变量的区别

《C++中全局变量和局部变量的区别》本文主要介绍了C++中全局变量和局部变量的区别,全局变量和局部变量在作用域和生命周期上有显著的区别,下面就来介绍一下,感兴趣的可以了解一下... 目录一、全局变量定义生命周期存储位置代码示例输出二、局部变量定义生命周期存储位置代码示例输出三、全局变量和局部变量的区别作用域

C++中assign函数的使用

《C++中assign函数的使用》在C++标准模板库中,std::list等容器都提供了assign成员函数,它比操作符更灵活,支持多种初始化方式,下面就来介绍一下assign的用法,具有一定的参考价... 目录​1.assign的基本功能​​语法​2. 具体用法示例​​​(1) 填充n个相同值​​(2)