总是用C++创建类?

Kon*_*che 17 c++ static static-methods

来自Java背景,对我来说,处理创建类的选择或者只是实现我可能需要的函数是新的.通常,在建模可能具有状态的东西时,这是毫无疑问的.

现在我正在实现一个没有main函数和静态成员函数的共享库.是否有些东西反对创建一个类来封装函数?

此外,我想在另一个文件中封装更多代码,尤其是辅助功能.执行代码总是相同的,并且它的状态不会改变,所以我想我会声明它们也是静态的 - 所以这里出现了同样的问题.

chr*_*ock 20

如果您发现每个方法都是静态的类,那么可能namespace更合适.


Dou*_* T. 10

坦率地说,这是一种哲学的,有点模糊的指导方针,但我更喜欢先使用最简单的东西,然后在需要时根据复杂性进行构建.

我的第一个偏好是

  1. 自由,无状态,无副作用的函数,对其参数执行某些操作/计算/转换并返回结果.

  2. 但是,如果这些参数中的任何一个演变为有状态,并且您的函数负责维护该状态,请考虑将有状态数据和操作该数据的方法包装到类中以实现良好的封装/数据隐藏.

文件I/O是一个有状态的例子.你打开一个文件,向它写一些数据,然后向上移动一个写指针,最后关闭它,这是你想要一个类的好例子.

自由函数最好的地方最明显的例子是数学.其他示例可能是执行正则表达式,将一种消息转换为另一种消息,等等.

(1)最简单,因为在最纯粹的形式中没有持久状态,一切都是变换的,你应该始终使用相同的输入获得相同的输出.易于测试,易于弄清楚它是如何工作的.理想情况下,我们不需要坚持任何状态,我们都可以这样编程.

(2)需要因为安全地更新状态是生活中必不可少的一部分,如果你不能进行任何数据隐藏或封装,你就会失去对正确和安全地维护状态的信心.

  • +1用于表示"函数是否具有状态是应该做出此决定的". (2认同)

AJG*_*G85 3

不确定我是否完全理解您,但是您可以创建一个提供静态方法的容器类。将构造函数设置为私有以防止人们实例化该类的实例可能是值得的。

class HelperFunctions
{
public:
    static void DoSomethingUseful() { /* useful bits */ }
    // yata yata
private:
    HelperFunctions(); // private default constructor
    HelperFunctions(const HelperFunctions&); // private copy constructor
};
Run Code Online (Sandbox Code Playgroud)

然后你可以做这样的事情:

HelperFunctions::DoSomethingUseful();
Run Code Online (Sandbox Code Playgroud)

但你不能做这样的事情:

HelperFunctions myHelperFunction; // private constructor = compile error
Run Code Online (Sandbox Code Playgroud)

您还可以出于组织非成员函数的目的创建命名空间。

namespace HelperFunctions
{
   void DoSomethingUseful() { /* useful bits */ }
   // yata yata
}
Run Code Online (Sandbox Code Playgroud)

请记住,您可以跨多个文件定义命名空间,也使这些命名空间对于对对象和函数(无论它们位于何处)进行分组特别有用。 这是更可取的,因为它在逻辑上分离了功能,使设计和预期用途更加明显

与 Java 不同,C++ 中的一切都是方法,我们可以在全局、命名空间或成员范围内拥有函数。您还可以拥有非成员友元函数,它们可以访问类的内部成员,而无需成为类本身的成员。

基本上你可以做任何你想做的事,包括搬起石头砸自己的脚。

编辑:为什么这么严重?

我并不是建议OP应该做什么不应该做什么。似乎他们是来自 Java 世界的 C++ 新手,在 Java 世界中,一切都是方法,所有“函数”都是类成员。对此,我的回答是首先展示如何在 C++ 中创建类似于 Java 中的东西,其次展示如何做其他事情以及为什么这样做。

正如其他人所说,出于各种原因,在可能的情况下优先使用非成员非朋友功能被认为是良好的做法。我同意,如果您不需要一个带有状态的对象,那么您可能不应该设计一个对象。然而,我不确定 OP 是否正在寻找有关设计和实现中最佳实践的哲学讨论,或者只是对等效 C++ 的好奇心。

我本希望我最后一句搬起石头砸自己脚的玩笑足以表明“仅仅因为你可以,并不意味着你应该”,但也许对这群人来说不是。

  • -1:是的,你*可以*做到这一点。但是,如果您构造一个具有公共静态的类,甚至将构造函数设置为“private:”,以便没有人可以实例化它,那么在我看来,您应该在命名空间内创建这些非成员函数。将它们放在类中除了命名空间范围(您可以直接获取)之外不会给您带来任何好处,并且可能意味着不存在的语义。 (12认同)
  • @Giovanni:请说事实并非如此。 (3认同)
  • @Billy、@AJG85、@platzhirsch:老实说,如果OP没有**接受**这个答案,我就不会投反对票。但OP特别说“有什么反对创建一个类来封装函数吗?” 我认为这个问题的答案是“是”。这向我表明,OP 认为这意味着它们“应该”是静态成员,而我试图引起人们注意,我们中的一些(大多数)人认为它们不应该是静态成员。 (2认同)