这种行为的原因是什么?它只是一种“安全措施/猜测”,即“如果你已经创建了自己的构造函数,你可能不想让这个隐式的构造函数挂在那里”吗? 还是它有一个技术原因,使得编译器无法在你自己创建构造函数后添加默认构造函数?
如果您已经添加了自己的构造函数,编译器就没有理由不添加构造函数-编译器可以做任何它想做的事情!然而,你必须看看什么最有意义:
因此,在每种情况下,您可以看到当前编译器的行为最有意义,以保留代码的可能意图。
当然,技术上并没有理由一定要以这种方式设计语言。
我认为有四个比较现实的选项:
选项1有些吸引人,因为我写的代码越多,我就越不需要无参数构造函数。有一天,我应该数一下我到底有多少次真正使用了默认构造函数...
选项2对我来说很好。
选项3违背了Java和C#在其他方面的规则。除了在Java中显式地使某些东西比默认情况更私有之外,你从来没有什么东西是显式地“删除”的。
选项4非常糟糕- 你绝对希望能够强制使用某些参数进行构造。 new FileStream()
甚至意味着什么?
因此,基本上,如果你接受默认构造函数有任何意义的前提,那么我认为一旦你提供自己的构造函数,抑制默认构造函数就有很大意义。
编辑。实际上,尽管我在第一次回答中所说的是有效的,但这才是真正的原因:
最初有C语言。C语言不是面向对象的(你可以采用面向对象的方式,但它并没有帮助你或强制任何事情)。
然后出现了C With Classes,后来更名为C++。C++是面向对象的,因此鼓励封装,并确保对象的不变量 - 在构造时以及任何方法的开头和结尾,对象处于有效状态。
自然而然的做法是强制类始终必须有一个构造函数,以确保它以有效状态开始 - 如果构造函数不必执行任何操作来确保此状态,则空构造函数将记录此事实。
但C++的目标是与C兼容,以至于尽可能多的C程序也是有效的C++程序(这不再是一个活跃的目标,并且C的演进与C++分离意味着它不再适用)。
这种情况的一个影响是struct
和class
之间的功能重复。前者按默认方式执行C的操作(默认公共),后者按良好的OO方式进行操作(默认情况下所有内容都是私有的,开发人员积极公开他们想要公开的内容)。
另一个影响是,为了使C struct
在C++中有效,因为C没有构造函数,所以必须有一种C ++方式看待它的含义。因此,虽然没有构造函数会违反积极确保不变性的面向对象实践,但C++认为这意味着有一个默认的无参数构造函数,其行为就像它有一个空的函数体。
现在,所有C structs
都是有效的C++ structs
,(这意味着它们与C++ classes
相同,所有成员和继承都是公共的),从外部看起来好像它只有一个无参数构造函数。
class
或struct
中放置了构造函数,则表示您使用的是C++/OO方式而不是C方式,并且没有必要使用默认构造函数。尽管它作为一种简写方式存在,但即使在不支持兼容性的情况下(它使用其他C++特性而不是C特性),人们仍然继续使用它。因此,当Java出现(在许多方面基于C++)以及后来的C#(以不同的方式基于C++和Java)时,它们将这种方法保留为程序员可能已经习惯的东西。removeDefaultConstructor
关键字。至少,我需要创建一个私有的无参数构造函数,以确保没有调用代码调用默认构造函数。这使语言更加复杂,最好不要这样做。总的来说,最好不要认为添加构造函数是删除默认构造函数,最好将完全没有构造函数视为一种语法糖,用于添加一个不执行任何操作的无参数构造函数。如果您未采取任何措施来控制对象的创建,则会添加默认的无参构造函数。一旦您创建了一个单独的构造函数来控制,编译器将“后退”,让您完全掌控。
如果不是这样,那么如果您只想通过带参数的构造函数构造对象,就需要一些明确的方法来禁用默认构造函数。
前提
这种行为可以看作是类具有默认公共无参数构造函数的自然扩展。根据所提出的问题,我们将此决定视为前提,并假设在此情况下不会对其进行质疑。
删除默认构造函数的方法
因此,必须有一种方法来删除默认的公共无参数构造函数。可以通过以下方式实现此删除:
选择最佳解决方案
现在我们问自己:如果没有无参数构造函数,它必须被替换为什么?和在什么类型的场景下,我们想要删除默认的公共无参数构造函数?
事情开始变得清晰。首先,它必须用带参数的构造函数或非公共构造函数替换。其次,您不想要无参数构造函数的情况包括:
结论
以上就是C#,C ++和Java允许删除默认公共无参构造函数的两种方法。
= delete
。 - jogojapan我认为这是由编译器处理的。如果您在 ILDASM
中打开 .net
程序集,即使该构造函数不在代码中,您也将看到默认构造函数。如果您定义了一个带参数的构造函数,则默认构造函数将不会被看到。
实际上,当您定义类(非静态)时,编译器提供此功能,以便您只创建一个实例。如果您想要执行任何特定操作,那么您肯定会有自己的构造函数。
默认构造函数只能在类没有构造函数时构建。编译器是这样编写的,以提供它作为备用机制。
如果您有一个参数化的构造函数,您可能不希望使用默认构造函数创建对象。如果编译器提供了默认构造函数,您将不得不编写一个无参构造函数并将其设置为私有,以防止使用无参数创建对象。
此外,您很可能会忘记禁用或“私有化”默认构造函数,从而导致潜在的难以捕获的功能错误。
现在,如果您想要通过默认方式或通过传递参数来创建对象,则必须明确定义一个无参构造函数。这是强制检查的,否则编译器会抱怨,从而确保没有漏洞。
一个类需要一个构造函数。这是强制性要求。
我会用另一个问题来回答你,为什么我们总是想要一个默认的无参数构造函数?有时这并不是所期望的,因此开发人员可以根据需要添加或删除它。
Foo() = default;
来获取默认值。 - MSalters