何时/如果要使非虚拟函数成为成员函数 我试图了解现代C++习惯用法和最佳实践,我想问一下,在编写一个类时,除了在类的类型需要运行时调度的情况下,还有一个时间应该使函数成为成员函数,而不是函数在类命名空间中的自由函数。

何时/如果要使非虚拟函数成为成员函数 我试图了解现代C++习惯用法和最佳实践,我想问一下,在编写一个类时,除了在类的类型需要运行时调度的情况下,还有一个时间应该使函数成为成员函数,而不是函数在类命名空间中的自由函数。,c++,member-functions,idioms,non-member-functions,C++,Member Functions,Idioms,Non Member Functions,我在想,也许是在你需要访问类的私有成员时,但是你也可以创建一个免费的朋友函数,并获得相同的效果,但有免费函数的好处,所以我不确定在这种情况下什么是最好的 使非虚拟函数成为成员是否合理?不仅合理,而且如果非虚拟函数对某个类中的数据进行操作,则通常使其成为该类的成员 使用非虚拟成员函数可以执行的任何操作,也可以使用无好友函数执行。区别在于是将函数调用为obj.foo()还是foo(obj)。在面向对象的程序中,前者是首选的,而后者仅用于(不常见的)有助于提高代码可读性的情况 这不是在“现代”C++中

我在想,也许是在你需要访问类的私有成员时,但是你也可以创建一个免费的朋友函数,并获得相同的效果,但有免费函数的好处,所以我不确定在这种情况下什么是最好的


使非虚拟函数成为成员是否合理?

不仅合理,而且如果非虚拟函数对某个类中的数据进行操作,则通常使其成为该类的成员

使用非虚拟成员函数可以执行的任何操作,也可以使用无好友函数执行。区别在于是将函数调用为
obj.foo()
还是
foo(obj)
。在面向对象的程序中,前者是首选的,而后者仅用于(不常见的)有助于提高代码可读性的情况


<>这不是在“现代”C++中发生的改变。一直以来都是这样。

面向对象编程的主要原则之一是封装。你把一些逻辑上放在一起的数据做成一个类。同一逻辑分组的扩展将是操作此数据的函数。这些职能应成为成员职能。让它们成为使类友好的自由函数违背了封装原则。

你几乎是在谈论一个
静态
类成员;不是非虚拟成员(两者都有使用的理由)。您指的是“自由函数的好处”是什么?@WhozCraig否,afaik静态类成员没有自由函数的好处。@user3867053 ADL解析到类的命名空间?即使你做了
foo.func()
,你也会明白这一点。很明显,每个人都在解释你的问题,这是一种观点,我不能责怪任何人。习语、最佳实践等等,从定义上讲,都是宽泛而主观的,剥猫皮的方法很多,等等。正是这些因素使问题以观点为基础,从而使问题得到了固执己见的答案。如果你在寻找真实的答案,我建议你用一个特定的实际问题和一个特定的解决方案来代替。但是这样写会抑制通用代码,例如,鼓励使用
std::begin
而不是
vector::begin
std::begin
实际上不是任何一个类的成员;它是一个模板,只需将
.begin
成员函数包装在容器类中,以使其适应一般用途。但真正起作用的是
.begin
成员函数,在非泛型代码中使用
std::begin
。@user3867053也许您正在考虑函数模板?您可以给出两段代码的示例,以及为什么您认为自由函数更有意义来阐明您的观点。@user3867053:但是还有
std::list::sort
std::sort
-为什么?因为前者本质上只适用于
std::list
——它利用了实现知识,所以无论如何都没有通用性。然后,当您想要排序时,可以随意调用
std::sort
。但是,如果您编写了一个知道如何对自己进行排序的新类,请给它一个
sort()
成员函数,并将其
std::sort
重载定义为该类的包装器,以便您还支持具有类实例并希望它以OOP方式对自己进行排序的非泛型代码;让朋友的功能而不是成员,就像封装一样。@ USSR667053,你是如何建议保护你的自由功能仅仅是为了推导,或者是你不再认为“现代”的东西?@ WooCurig我来到这里是为了学习,而不是为了教书,所以我想知道什么是现代,而不是声明什么是。乍一看,
protected
似乎是成员函数的良好用途。@user3867053、
friend
函数不是继承的,继承是OOP的基石之一。修改一次,让所有派生类继承行为(虚拟或非虚拟)。和朋友在一起,你违反了这个原则。@user3867053,还有一点。最终,当您拥有一个巨大的类库(例如STL)时,使用
friend
方法,您将得到大量的friend函数,可能会分布在大量的文件中,并快速确定哪个函数耦合到哪个函数,这将变得痛苦且容易出错。