Private methods vs Lambda in C++
我的问题是指:
使用lambda表达式与私有方法
现在lambda函子是C++的一部分,它们可以用来清除类的接口。C++中如何使用LAMBDA与私有方法比较?对于整洁的类接口有更好的选择吗?
- 私有方法与类接口有什么关系?
- @Kerreksb他们是其中的一部分。你听说过friend关键字。
- friend关键字是一个非常糟糕的实践,如果你使用friend关键字,你就有一个设计问题。此外,这仍然不能使它们成为类接口的一部分,因为非友元类或方法将无法使用它们。
- @用户1708860我不同意,Qt5的qtbase中的find -name"*.h" | xargs grep friend | wc -l,目前显示1272。还有其他的例子。另外,如果您使用私有成员,我认为它是类接口的一部分,尽管它是私有的。
- 只举一个谷歌快速搜索的例子。stackoverflow.com/questions/203616/…只是因为一个常用的库不能使它成为好的库,所以您永远无法知道它们为什么使用它。
- @用户1708860,这完全是胡说八道。你链接到的答案被实际C++专家严重压低(与C显然相反),并且评论解释了为什么它是错误的。—但它并没有改变这样一个事实:private函数不是类接口的一部分。
- 至于接口部分,首先应该定义C++中的"类接口"。如果你看其他语言,或者en.wikipedia.org/wiki/application_programming_interface,你就会发现私有方法和成员不会进入类接口的类别。
- @用户1708860我想你是PIMPL和Bridge的支持者。
- @Konradrudolph,谢谢你改变了我对朋友封装部分的看法,尽管如此,如果你使用朋友的话,我仍然认为你的设计应该重新考虑。正如我所说,链接只是我搜索的第一件事。用户1095108,我有点……。
- 私有函数是接口的一部分,对于不可复制的每个示例,这是= delete的旧方法。此外,私有功能在过载解决(class A{void f(char); public: f(float)}; a.f(42); // failed中)期间也会参与,因此会干扰公共接口。
虽然lambda确实可以替换一些私有成员函数,但是把它们看作是清理类接口的方法,对于lambda和私有成员函数的看法过于狭隘。
私有成员函数(和一般的函数)是代码重用的基本单位。它们允许您编写一段逻辑,然后将其隐藏在函数名后面。
尽管lambda可以在特定的上下文中替换私有成员函数,但是它们可以替换一个对象,该对象的函数与它一起是一个成员,而这个对象要多得多。由于lambda能够捕获它们周围的上下文,因此您可以获得一种创建代码块的方法,该代码块不仅包含对象,还包含局部变量的状态。在lambda之前,您需要为它创建一个特殊的类;lambda允许您动态地创建此类类,以获得更好的可读性。
- 是的,您不需要额外的私有成员或单独的类来存储本地状态,但是如何使用它们来隐藏信息呢?您的意思是说,如果要保存本地状态,请使用lambda,否则请使用私有函数?
- @用户1095108具有讽刺意味的是,它是公共方法,可以帮助您隐藏信息,因为它们会向调用者隐藏实现的细节。私有方法不是类接口的一部分,它们本身对类的用户是隐藏的;与向用户隐藏信息的公共方法不同,从调用方的角度来看,私有方法不存在。lambda也是如此(除非定义lambda类型的公共变量):它们完全对调用方隐藏。
- lambda对象不是函数的等价物吗?在所有情况下,它们不应该被认为是一种可能的常规功能的替代品吗?它们可以重用,也可以复制粘贴。我不知道如何理解你的帖子。lambda可以比私有成员函数做"更多"的工作,那么为什么它们不优越呢?
- @用户1095108 lambdas在一种情况下会替换私有函数-当您需要将一段代码传递给另一个需要回调您的函数时。与私有函数相比,lambda在这方面给了您更多的灵活性。但是,还有一些地方您需要lambda不需要的函数,例如子类可以覆盖的私有虚拟函数,或者需要消除复制粘贴的共享逻辑块。关键是,即使在没有单个回调的系统中,您仍将使用私有函数进行代码组织;在这种情况下,lambda将是无用的。
- 您可以将lambda放入std::function中,并通过这种方式对其进行调整,以便在更多情况下发挥作用。它可以通过这种方式共享,甚至可能被重写(通过赋值)。
- @用户1095108当您将lambda放入std::function时,您将它调整为在类似回调的情况下使用(即当您需要将封装的逻辑块传递给函数时)。LAMBDAS是多功能的,您可以对它们进行重写,但是您将使用lambdas而不是要覆盖的纯函数来打破C++的惯用方式。
对于整洁的类接口有更好的选择吗?
我经常使用的一种方法是在一个未命名的命名空间中提供一系列具有文件作用域的函数,这些函数充当我的成员函数的"助手"。
例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| // Foobar.cpp
#include"Foobar.h"
namespace {
void someHelper()
{
std::cout <<"I'm a helper!" << std::endl;
}
}
void Foobar::someMemberFunc()
{
someHelper();
[...]
} |
当然,也可以在此未命名的命名空间中声明lambda和/或类。此未命名命名空间中声明的任何内容都只能从同一翻译单元(如cpp文件)中访问。
- 当您需要访问对象的私有成员时,这并不能解决许多问题,除非您将它们公开并作为参数传递,但我只能祝您好运并玩得开心:)
- @用户1708860我认为这些方法不能访问私有成员是一件好事。保持对象不变性的函数绝对应该是成员。任何不保持不变性的东西最好放在班外。如果客户机需要,那么具有外部链接的非成员函数是最好的。但是,如果成员需要通常不可重用的"助手",那么我提供的习惯用法可以保持很强的封装性,而不会污染名称空间/接口,真正有助于缩短构建时间。
- 您可以始终使用一个详细的名称空间,使它也可以进行单元测试。
lambda是一种将逻辑移入代码流的方法。唯一的目的是提高可读性,它们可以帮助或伤害
- 如果private/lambda很短,读者通常更容易当场理解它,而不必记住稍后查看不同的函数。
- 如果private/lambda很长,并且与调用它的代码不一致,这会分散读者对代码中更大模式的注意力。想象一下,如果你正在阅读这些stackoverflow答案中的一个,突然不得不停下来阅读stackenglish对空的描述来理解答案。你更愿意看到一个"可选信息"的超链接,而不是内容的复制/粘贴。
- 构造保存upvalue参数的lambda比构造私有函数执行相同操作要容易得多。这可以提高可读性,因为lambda在实现该目标时没有太多样板文件。
- lambda很难在代码段之间共享。如果您发现自己在许多地方调用相同的函数,私有函数可能是更好的匹配。
How does lambda use vs private method use compare in C++
我们可以捕获这个指针,因此可以访问类的内部,而不会弄乱它的接口。以前,在某些情况下,需要在STL算法中使用成员或友元函数(与bind和mem_fn结合使用)。
另外,我们应该尽量保持最小的接口,因为更改接口的成本更高。因此,像pimpl这样的习惯用法很流行,同样的原因lambda可能比成员函数更受欢迎。正如另一个人所提到的,我们应该考虑到函数也是重用工具,但是在这种情况下,我更喜欢具有私有函数的PIMPL,它否定了为此目的重用lambda。
如果你问我,这里面有个人品味的问题,两者之间的差别并不大。
lambda确实很适合STL算法,而私有方法却不能做到这一点,另一方面,如果您想重用代码,我发现私有方法更好。
这个问题展示了lambdas的最佳用法:lambdas
就我个人而言,我更喜欢私人方法,尤其是在你提出的情况下。不应使用lambda代替私有方法。它使函数的主体变得混乱,并将视线从主逻辑上转移开。
虽然它使类变得整洁,但它使函数变得混乱,我觉得更糟。