在C++中删除纯静态公共接口上的复制/赋值运算符是否有意义

Does it make any sense to delete copy/assignment operators on a purely static public interface in C++?

本文关键字:复制 赋值运算符 有意义 是否 接口 C++ 删除 静态      更新时间:2023-10-16

我正在编写一个类,该类在C++中有一个公共静态方法和几个私有方法。在这种情况下,显式删除(请参阅下面的代码)复制和赋值运算符是否有意义?

public:
    static MyReturnType* CreateSomeMock(const myType input);
    MyClass(const MyClass&) = delete;
    MyClass& operator=(const MyClass&) = delete;
private:
    static ...

我倾向于说我不应该担心有人试图复制或分配给没有实例变量的默认构造类。我只是不是 100%,很好奇社区认为什么是最佳实践。

更新 1

我已将私有方法移至.cpp文件中定义的非成员函数。标头仍然包含公共成员函数CreateSomeMock,我仍然对赋值/复制构造感到好奇 =)。

更新 2

这个"类"本质上是一个命名空间。我很欣赏围绕这一点的所有答案,并且还想在这种情况下将其保持在问题= delete部分的主题上(我同意在这一点上确实应该避免......但我举个例子,它有时会发生)。

具有一个或多个静态函数的类与命名空间中的几个函数之间的唯一区别是使用模板时:可以将类用作模板参数,但不能用作命名空间。

或者,可以使用静态方法作为模板参数,但在向类或命名空间添加更多方法时,该参数不会缩放。

例如,如果您有:

class X {
public:
  static void a();
  static void b();
};

您可以在模板中将其用作some_template<X>,并且您的模板可以在模板参数上调用 a 和 b:

template<typename T>
void some_template() { T::a(); T::b(); }

但是,如果X是命名空间,则需要两个模板参数: some_template<X::a, X::b>

如果这是一个有效的用例,所以你确实需要一个静态类,你可能希望避免意外创建它的实例。

一个实际的原因是,在C++中,每个对象都需要大于零的大小:当有人意外创建此类的实例时,即使最小,它也会产生成本。

delete它们不会有什么坏处,这样编译器就不会为您创建默认的。但是,您应该遵循 3 规则并显式声明析构函数(这并不重要)。

不过,这门课毫无意义。似乎您应该将非成员函数声明为命名空间的一部分:

namespace myFactoryPattern {
    MyReturnType* CreateSomeMock(const myType input);

这种模式称为静态类。它与命名空间(您可以将其视为替代方法)的不同之处在于,模板可以专用于它。这是预期的,但不是必需的删除:(在类或基类中)

  • 默认、复制和移动构造函数
  • 复制和移动作业

或者,您也可以删除:

  • 析构函数(不允许非指针和delete
  • operator new(size_t)operator new[](size_t)(不允许new到永远不会删除的裸指针)

后者有一个有趣的因素,让每个人都感到惊讶,并从他们的时间中窃取时间来了解正在发生的事情以及为什么他们不能创建和实例。

或者 - 您可能只允许实例。这真的没有人,有经验的程序员不会创造任何东西;但是,您仍然可以将其传递给模板函数,这些函数期望在静态方法满足所需接口的情况下传递成员。