当前位置: 首页 > 知识库问答 >
问题:

为什么默认的无参数构造函数在您创建一个带参数的构造函数时消失

慕项明
2023-03-14

在C#、C和Java中,当你创建一个带参数的构造函数时,默认的无参数构造函数就消失了。我一直只是接受这个事实,但现在我开始想为什么。

这种行为的原因是什么?这仅仅是一个“安全度量/猜测”,说“如果你已经创建了自己的构造函数,你可能不希望这个隐含的函数四处游荡”?或者它有一个技术原因,使得编译器不可能在你自己创建构造函数后添加一个?

共有3个答案

郭辉
2023-03-14

编辑事实上,虽然我在第一个答案中所说的是正确的,但这才是真正的原因

一开始有C。C不是面向对象的(您可以采取面向对象的方法,但它不能帮助您或强制执行任何东西)。

然后是带有类的C,后来被重命名为C。C是面向对象的,因此鼓励封装,并确保对象的不变性——在构造时以及在任何方法的开始和结束时,对象都处于有效状态。

这样做很自然,就是强制一个类必须总是有一个构造函数来确保它以有效的状态开始——如果构造函数不需要做任何事情来确保这一点,那么空构造函数将记录这个事实。

但C的目标是与C兼容,尽可能使所有有效的C程序都是有效的C程序(不再是一个活跃的目标,C向C的演化意味着它不再有效)。

其中一个影响是structclass之间的功能重复。前者以C方式做事(默认情况下一切都是公共的),而后者以良好的OO方式做事(默认情况下一切都是私有的,开发人员积极地公开他们想要公开的东西)。

另一个是,为了使C结构(因为C没有构造函数,所以它不能有构造函数)在C中有效,那么C看待它的方式必须有一个意义。因此,虽然没有构造函数会违背积极确保不变量的OO实践,但C认为这意味着有一个默认的无参数构造函数,其行为就像它有一个空的主体一样。

所有的C结构现在都是有效的C结构,(这意味着它们与C相同,包含所有内容-成员和继承-公共)从外部处理,就像它有一个单一的、无参数的构造函数。

然而,如果您确实将构造函数放在结构中,那么您是在以C /OO方式而不是C方式做事,并且不需要默认构造函数。

由于它是一种速记工具,所以即使在不具备兼容性的情况下,人们也会继续使用它(它使用了C中没有的其他C特性)。

因此,当Java出现(在许多方面基于C)和后来的C#(在不同方面基于C和Java)时,他们保留了这种方法,因为程序员可能已经习惯了这种方法。

Stroustrup在他的《C编程语言》(The C Programming Language)一书中写到了这一点,更是如此,他更加关注C语言在设计和发展过程中的“为什么”。

===原答案===

假设这没有发生。

假设我不想要一个无参数构造函数,因为如果没有它,我无法将类置于有意义的状态。事实上,C#中的struct可能会发生这种情况(但如果您不能在C#中有意义地使用全零和全空struct,那么您最多只能使用一个非公开可见的优化,否则在使用struct时会有设计缺陷)。

为了使我的类能够保护它的不变量,我需要一个特殊的DetveDefaultConstructor关键字。至少,我需要创建一个私有的无参数构造函数,以确保没有调用代码调用默认值。

这使语言更加复杂。最好不要这样做。

总之,最好不要将添加构造函数视为删除默认值,最好将根本没有构造函数视为添加无参数构造函数的语法糖,因为无参数构造函数什么都不做。

屈俊远
2023-03-14

当然,语言必须这样设计没有技术上的原因。

我可以看到四个有点现实的选择:

  1. 根本没有默认构造函数
  2. 当前情景
  3. 默认情况下始终提供默认构造函数,但允许显式抑制它
  4. 始终提供默认构造函数而不允许其被抑制

选项1有点吸引人,因为我编写的代码越多,就越不需要无参数构造函数。总有一天我应该计算一下我实际使用默认构造函数的频率。。。

选择2我同意。

对于语言的其余部分,选项3与Java和C#的流程相反。没有任何东西是可以显式“删除”的,除非显式地使事物比Java中默认的更加私有。

选项4非常糟糕-您绝对希望能够使用某些参数强制构造。newfilestream()甚至意味着什么?

所以基本上,如果你接受提供默认构造函数有意义的前提,我相信一旦你提供了自己的构造函数,就抑制它是很有意义的。

师曦
2023-03-14

如果您已经添加了自己的构造函数,那么编译器没有理由不能添加构造函数——编译器几乎可以做任何它想做的事情!然而,你必须看看什么是最有意义的:

  • 如果我没有为非静态类定义任何构造函数,我很可能希望能够实例化该类。为了允许这样做,编译器必须添加一个无参数构造函数,这除了允许实例化之外没有任何效果。这意味着我不必在代码中包含一个空构造函数来使它工作。
  • 如果我定义了自己的构造函数,尤其是带参数的构造函数,那么我很可能有自己的逻辑,必须在创建类时执行。如果编译器在这种情况下创建一个空的、无参数的构造函数,它将允许某人跳过我编写的逻辑,这可能会导致我的代码以各种方式中断。如果在这种情况下我想要一个默认的空构造函数,我需要明确地说出来。

因此,在每种情况下,您都可以看到当前编译器的行为在保留代码的可能意图方面最有意义。

 类似资料:
  • 当Java中给出参数构造函数时,为什么默认的无参数构造函数会失败? 这个设计有什么意义? 例如:

  • 实际上,我不明白无参数构造函数和默认构造函数的区别是什么。 在创建名为cFrame的Test对象时,是否调用此类的默认构造函数?

  • 问题内容: 如果父类中有带参数的构造函数,为什么需要默认构造函数(显式) 这将是一个错误。 问题答案: 这里有两个方面的工作: 如果 确实 明确指定了构造函数(如中所述),则Java编译器将 不会 为您创建无参数构造函数。 如果您未明确指定构造函数(如所示),则Java编译器将为您创建一个无参数的构造函数,如下所示: (可访问性取决于类本身的可访问性。) 试图调用超类无参数构造函数-因此它必须存在

  • 问题内容: 其实我不明白,无参数构造函数和默认构造函数有什么区别。 创建名为cFrame的Test对象时,这是否调用此类的默认构造函数? 问题答案: 该构造函数是一个无参数的构造函数,代表您的Java编译器插入; 它包含对(not )的调用,这是默认行为。如果实现任何构造函数,则不再收到默认的构造函数。 JLS-8.8.9。默认构造函数说(部分), 如果一个类不包含构造函数声明,则隐式声明一个没有

  • 我的问题是关于OOP(C)中的构造函数。当我在一个类中将默认构造函数定义为private,并且在main中将该类的一个对象初始化为default时,就会出现默认构造函数不可访问的错误。这很好。但我也在Public部分中使用默认参数构造函数,当我再次在main中初始化对象时,就会出现对函数重载的不明确调用。所以我的问题是,如果不能从main访问私有构造函数,那么编译器应该调用公共部分中的构造函数,这

  • 本文向大家介绍解析C++中构造函数的默认参数和构造函数的重载,包括了解析C++中构造函数的默认参数和构造函数的重载的使用技巧和注意事项,需要的朋友参考一下 C++构造函数的默认参数 和普通函数一样,构造函数中参数的值既可以通过实参传递,也可以指定为某些默认值,即如果用户不指定实参值,编译系统就使形参取默认值。 【例】 程序运行结果为: 程序中对构造函数的定义(第12-16行)也可以改写成参数初始化