通常,为了完全防止类的客户端代码实例化,您可以声明该类final
,并且
当非是时声明类final
是必要的,对于抽象类,为了防止派生类的基类子对象的实例化。public
protected
要部分禁止实例化,您可以
这可以防止自动和静态变量,但不会防止使用new
.
- 使类的分配函数 (the
operator new
) 非public
.
这可以防止通过客户端代码中的普通new
- 表达式进行动态分配,但它不提供自动和静态变量,或其他对象的子对象,也不会防止通过::new
使用全局分配功能的 - 表达式进行动态分配。
还有其他相关技术,例如带有额外参数的分配函数,使- 表达式new
异常复杂和不切实际。我曾经使用它来强制使用特殊宏来动态分配对象,例如用于shared-from-this class。但那是在 C++11 支持参数转发之前的时间。现在一个普通的函数就可以完成这项工作,这样的函数可以成为friend
类的一个。
代码使用至少一个版本的 clang 编译器编译的事实-std=gnu++1z
是由于该编译器中的错误和/或语言扩展。
代码不应编译,因为它调用已删除的默认构造函数。并且它不能使用例如 MinGW g++ 5.1.0 编译,即使使用-std=gnu++1z
.
代码使用至少一个版本的 clang 编译器编译的事实-std=gnu++1z
可能是由于该编译器中的错误和/或语言扩展。正确的行为是什么,尚不清楚,因为
尽管代码使用 clang 和 Visual C++ 2015 编译,但它不能使用例如 MinGW g++ 5.1.0 编译,即使使用-std=gnu++1z
.
直观地说,delete
如果代码应该编译,那将是毫无意义的,但在 C++ 中允许许多无意义的构造。
问题在于类是否是聚合(在这种情况下,new
表达式执行聚合初始化),这取决于删除的默认构造函数是否可以视为用户提供的。正如用户TartanLlama在评论中解释的那样,用户提供的要求是
C++11 §8.4.2/4
”一个特殊的成员函数是用户提供的,如果它是用户声明的并且在其第一次声明时没有显式地默认或删除。
即,尽管delete
这个问题示例中的默认构造函数声明了该构造函数,但它不是用户提供的(其他成员也是如此),因此该类是一个聚合类。
我能找到的关于这个措辞的唯一缺陷报告是DR 1355,但是它只涉及使用“特殊成员”这个词的问题,并建议删除这些词。但是,考虑到这个问题所展示的效果,并考虑到一个函数只能在其第一次声明时被删除,措辞很奇怪。
正式总结一下,从 C++11 开始(我还没有检查 C++14),代码应该可以编译。但这可能是标准中的一个缺陷,措辞不反映意图。而且由于 MinGW g++ 5.1.0 不编译代码,截至 2015 年 10 月,依赖代码编译不是一个好主意。