Umu*_*bak 35 c++ encapsulation member-functions effective-c++ non-member-functions
虽然对类设计中的一些事实感到困惑,特别是函数是否应该是成员,但我查看了有效的c ++并找到了第23项,即将非成员非友元函数更喜欢成员函数.第一手阅读Web浏览器示例有一定意义,但是该示例中的便捷函数(在本书中命名为非成员函数)会改变类的状态,不是吗?
所以,第一个问题,他们不应该成为会员吗?
进一步阅读,他认为STL函数,实际上某些类没有实现的函数是在stl中实现的.继他们演变成被包装到一些合理的命名空间,如一些便利功能,这本书的想法std::sort,std::copy从algorithm.例如,vector类没有sort函数,并且使用stl sort函数,因此它不是向量类的成员.但是也可以将相同的推理延伸到向量类中的某些其他函数,例如,assign这样也不能作为成员实现,而是作为便利函数实现.但是,这也会改变对象的内部状态,例如它操作的排序.那么这个微妙但重要(我猜)问题背后的理由是什么呢?
如果你有权访问这本书,你可以为我澄清这些要点吗?
Mat*_* M. 37
绝对没有必要访问这本书.
我们在这里讨论的问题是依赖和重用.
在设计良好的软件中,您尝试将项目彼此隔离以减少依赖关系,因为在需要更改时,依赖关系是一个需要克服的障碍.
在精心设计的软件中,您应用DRY原则(不要重复自己),因为当需要进行更改时,必须在十几个不同的地方重复它,这很痛苦,而且容易出错.
"经典"OO思维模式在处理依赖关系方面越来越糟糕.通过直接依赖于类的内部的许多方法,最轻微的改变意味着整个重写.不一定如此.
在C++中,STL(不是整个标准库)的设计具有以下明确的目标:
因此,容器公开了明确定义的接口,这些接口隐藏了它们的内部表示,但仍然提供了对它们封装的信息的足够访问,以便可以在它们上执行算法.所有修改都通过容器接口进行,以保证不变量.
例如,如果您考虑sort算法的要求.对于STL使用的(通常)实现,它需要(来自容器):
因此,任何提供随机访问且不是关联的容器(理论上)都适合通过(例如)快速排序算法进行有效排序.
C++中满足此要求的容器是什么?
dequevector如果你注意这些细节,你可以写的任何容器.
sort为每个人重写(复制/粘贴/调整)会是浪费,不是吗?
请注意,例如,有一种std::list::sort方法.为什么?因为std::list不提供随机访问(非正式地myList[4]不起作用),因此sortfrom算法不适合.
Omn*_*ous 19
我使用的标准是,如果一个函数可以通过成员函数显着更有效地实现,那么它应该是一个成员函数.::std::sort不符合这个定义.事实上,在外部和内部实施它没有任何效率差异.
通过实现成员(或朋友)功能来提高效率意味着通过了解类的内部状态可以大大提高效率.
界面设计的一部分技术是找到最小的成员函数集,这样您可能希望在对象上执行的所有操作都可以合理有效地实现.而且这个集合不应该支持不应该在类上执行的操作.因此,您不能只实现一堆getter和setter函数并将其称为好.
asc*_*bol 11
我认为这个规则的原因是通过使用成员函数,你可能会偶然地依赖于类的内部.改变类的状态不是问题.真正的问题是,如果修改类中的某些私有属性,则需要更改的代码量.保持类(公共方法)的接口尽可能小,既减少了在这种情况下需要做的工作量,又减少了对私有数据做一些奇怪的事情的风险,使得实例处于不一致状态.
AtoMerZ也是对的,非成员非朋友函数也可以模板化并重用于其他类型.
顺便说一句,你应该购买你的有效C++的副本,这是一本很棒的书,但不要总是遵守本书的每一项.面向对象设计既有良好的实践(来自书籍等)和经验(我认为它也是用有效的C++编写的).
各种想法:
friend.object.function(x, y, z)符号,恕我直言,这是非常方便、富有表现力和直观的。它们还可以更好地与许多 IDE 中的发现/完成功能配合使用。成员函数和非成员函数的分离有助于传达类的基本性质、不变量和基本操作,并在逻辑上对附加组件和可能的临时“便利”功能进行分组。想想托尼·霍尔 (Tony Hoare) 的智慧:
“构建软件设计有两种方法:一种方法是使其简单到没有明显缺陷,另一种方法是使其复杂到没有明显缺陷。第一种方法方法要困难得多。”
随着非成员功能的复杂性扩展或获取额外的依赖项,这些功能可以移到单独的头文件和实现文件中,甚至是库中,因此核心功能的用户只需为使用他们想要的部分“付费”。
(Omnifarious 的答案是必读的,如果对您来说是新的,请阅读三次。)
| 归档时间: |
|
| 查看次数: |
11223 次 |
| 最近记录: |