38

为了使对象不可复制,我们可以显式删除其复制构造函数和复制赋值运算符。

public我的问题是:在课堂的,privateprotected部分中做这件事的正确位置是什么?而且 - 这个选择有什么不同吗?

4

5 回答 5

45

什么是正确的地方——在课堂的公共、私人或受保护的部分?

会把它们放在publicsection中。

这是因为删除构造函数或赋值运算符与生成private/是正交的protected;当这些没有被删除时,它们是public默认的。在我看来,将删除内容放在这两个部分之一中似乎是在暗示“如果我没有删除它们,我会将它们设为私有/受保护”——这不是您想在您的案例中传达的信息。

但是请注意,编译器并不关心您将删除放在哪个部分。

于 2019-03-17T10:38:05.320 回答
21

我们把删除的定义放在哪里有什么不同吗?

从纯语言的角度来看,它绝对是零差异。名称查找和重载解析发生在访问检查之前。并且尝试在重载决议结束时引用已删除的函数会使您的程序格式错误。编译器可能会或可能不会发布关于可访问性的另一个诊断,但程序已经有一个必须报告的错误。

因此,您可以将已删除的定义与您想要的任何可访问性一起放置。我认为大多数人都会将其保密,以符合使类不可复制的“旧”做法(将这些成员的声明放在类的私有部分,而不是定义它们),如果只是为了帮助那些谁知道旧方法会更快“得到它”。混合成语,如果你愿意的话。

如果需要同时支持 C++03 和 C++11 模式,标记为私有也是无法避免的。在宏的帮助下,可以轻松地使标头符合这两个标准:

#if __cplusplus >= 201103L
  #define DELETED_DEFINITION = delete
#else
  #define DELETED_DEFINITION
#endif

class noncopyable {
private:
  // This header can be compiled as both C++11 and C++03
  noncopyable(noncopyable const&) DELETED_DEFINITION;
  void operator=(noncopyable const&) DELETED_DEFINITION;
};
于 2019-03-17T10:26:46.530 回答
16

从 Scott Meyers 的书 Effective Modern C++ (Item 10) 看来,最好将它们定义为 public

按照惯例,被删除的函数被声明为公共的,而不是私有的。这是有原因的。当客户端代码尝试使用成员函数时,C++ 在删除状态之前检查可访问性。当客户端代码尝试使用已删除的私有函数时,一些编译器只会抱怨该函数是私有的,即使该函数的可访问性并不会真正影响它是否可以使用。在修改遗留代码以将私有且未定义的成员函数替换为已删除的成员函数时,值得牢记这一点,因为将新函数公开通常会导致更好的错误消息。

此外,我认为删除的复制构造函数/赋值应该是类接口的一部分,与所有类用户共享。此类信息不应通过保密来保密。

于 2019-03-17T21:43:22.390 回答
7

deleteprivate访问一样好。

如果函数是通过重载决议选择的,那么的效果delete会导致错误。

private如果函数是通过类外部或其朋友的重载决议选择的,则的效果会导致错误。

如果这两个错误都适用,则最终结果是相同的,但public可能有助于避免编译器关于访问权限的消息,这可能会导致混淆。

于 2017-01-30T17:21:57.833 回答
2

deleted 函数的访问是无关紧要的。事实上,对于类成员来说,添加一个额外的访问说明符 ( delete:) 会更有意义。我怀疑他们没有这样做的原因是它不适用于非成员函数。

对于诸如复制构造函数之类的东西,将其放在public部分中在风格上更有意义。类没有复制构造函数这一事实是了解类接口的一个非常重要的事实。

对于将特定重载声明为已删除以在编译器时检测错误的内部函数,在与所有其他重载相同的部分中声明该函数是有意义的。

于 2017-01-30T17:20:38.923 回答