java 为什么构造函数总是与类具有相同的名称以及它们是如何隐式调用的?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6979612/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why constructors will always have same name as of class and how they are invoked implicitly?
提问by Microsoft Developer
I want to know that why the name of constructor is always same as that of class name and how its get invoked implicitly when we create object of that class. Can anyone please explain the flow of execution in such situation?
我想知道为什么构造函数的名称总是与类名称的名称相同,以及当我们创建该类的对象时如何隐式调用它。任何人都可以解释在这种情况下的执行流程吗?
回答by fredoverflow
I want to know that why the name of constructor is always same as that of class name
我想知道为什么构造函数的名称总是与类名称相同
Because this syntax does not require any new keywords. Aside from that, there is no good reason.
因为这种语法不需要任何新的关键字。除此之外,没有充分的理由。
To minimize the number of new keywords, I didn't use an explicit syntax like this:
class X { constructor(); destructor(); }
Instead, I chose a declaration syntax that mirrored the useof constructors.
class X { X(); ~X();
This may have been overly clever. [The Design And Evolution Of C++, 3.11.2 Constructor Notation]
为了尽量减少新关键字的数量,我没有使用这样的显式语法:
class X { constructor(); destructor(); }
相反,我选择了一种反映构造函数使用的声明语法。
class X { X(); ~X();
这可能过于聪明了。【C++的设计与演进,3.11.2构造函数记法】
Can anyone please explain the flow of execution in such situation?
任何人都可以解释在这种情况下的执行流程吗?
The lifetime of an object can be summarized like this:
对象的生命周期可以总结如下:
- allocate memory
- call constructor
- use object
- call destructor/finalizer
- release memory
- 分配内存
- 调用构造函数
- 使用对象
- 调用析构函数/终结器
- 释放记忆
In Java, step 1 always allocates from the heap. In C#, classes are allocated from the heap as well, whereas the memory for structs is already available (either on the stack in the case of non-captured local structs or within their parent object/closure). Note that knowing these details is generally not necessary or very helpful. In C++, memory allocation is extremely complicated, so I won't go into the details here.
在 Java 中,步骤 1 总是从堆分配。在 C# 中,类也是从堆分配的,而结构的内存已经可用(在未捕获的本地结构的情况下在堆栈上或在它们的父对象/闭包内)。请注意,了解这些详细信息通常没有必要或很有帮助。在C++中,内存分配极其复杂,这里不再赘述。
Step 5 depends on how the memory was allocated. Stack memory is automatically released as soon as the method ends. In Java and C#, heap memory is implicitly released by the Garbage Collector at some unknown time after it is no longer needed. In C++, heap memory is technically released by calling delete
. In modern C++, delete
is rarely called manually. Instead, you should use RAII objects such as std::string
, std::vector<T>
and std::shared_ptr<T>
that take care of that themselves.
第 5 步取决于内存的分配方式。方法一结束,栈内存就会自动释放。在 Java 和 C# 中,堆内存在不再需要后由垃圾收集器在某个未知时间隐式释放。在 C++ 中,堆内存在技术上是通过调用delete
. 在现代 C++ 中,delete
很少被手动调用。相反,您应该使用 RAII 对象,例如std::string
,std::vector<T>
并std::shared_ptr<T>
自行处理。
回答by Oded
Why? Because the designers of the different languages you mention decided to make them that way. It is entirely possible for someone to design an OOP language where constructors do not have to have the same name as the class (as commented, this is the case in python).
为什么?因为你提到的不同语言的设计者决定以这种方式制作它们。有人完全有可能设计一种 OOP 语言,其中构造函数不必与类具有相同的名称(正如所评论的,python 就是这种情况)。
It is a simple way to distinguish constructors from other functions and makes the constructing of a class in code very readable, so makes sense as a language design choice.
这是区分构造函数和其他函数的一种简单方法,并使代码中的类的构造非常可读,因此作为一种语言设计选择是有意义的。
The mechanism is slightly different in the different languages, but essentially this is just a method call assisted by language features (the new
keyword in java and c#, for example).
不同语言的机制略有不同,但本质上这只是语言特性(new
例如java和c#中的关键字)辅助的方法调用。
The constructor gets invoked by the runtime whenever a new object is created.
每当创建新对象时,运行时都会调用构造函数。
回答by user2148437
Seem to me that having sepearte keywords for declaring constructor(s) would be "better", as it would remove the otherwise unnecessary dependency to the name of the class itself.
在我看来,使用 sepearte 关键字来声明构造函数会“更好”,因为它会消除对类名本身的不必要依赖。
Then, for instance, the code inside the class could be copied as the body of another without having to make changes regarding name of the constructor(s). Why one would want to do this I don't know (possibly during some code refactoring process), but the point is one always strives for independency between things and here the language syntax goes against that, I think.
然后,例如,可以将类中的代码复制为另一个的主体,而无需更改构造函数的名称。我不知道为什么要这样做(可能在某些代码重构过程中),但重点是人们总是努力争取事物之间的独立性,而我认为这里的语言语法与此背道而驰。
Same for destructors.
对于析构函数也是如此。
回答by iammilind
One of the good reasons for constructor having the same name is their expressiveness. For example, in Java you create an object like,
构造函数具有相同名称的一个很好的原因是它们的表现力。例如,在 Java 中,您创建一个对象,例如,
MyClass obj = new MyClass(); // almost same in other languages too
Now, the constructor is defined as,
现在,构造函数定义为,
class MyClass {
public MyClass () {... }
}
So the statement above very well expresses that, you are creating an object and while this process the constructor MyClass()
is called.
所以上面的语句很好地表达了,你正在创建一个对象,而在这个过程MyClass()
中调用了构造函数。
Now, whenever you create an object, it always calls its constructor. If that class is extend
ing some other Base class, then their constructor will be called first and so on. All these operations are implicit. First the memory for the object is allocated (on heap) and then the constructor is called to initialize the object. If you don't provide a constructor, compiler will generate one for your class.
现在,每当你创建一个对象时,它总是调用它的构造函数。如果该类正在extend
调用其他一些 Base 类,则将首先调用它们的构造函数,依此类推。所有这些操作都是隐式的。首先分配对象的内存(在堆上),然后调用构造函数来初始化对象。如果您不提供构造函数,编译器将为您的类生成一个。
回答by Steve Jessop
In C++, strictly speaking constructors do not have names at all. 12.1/1 in the standard states, "Constructors do not have names", it doesn't get much clearer than that.
在 C++ 中,严格来说构造函数根本没有名字。标准中的 12.1/1,“构造函数没有名称”,没有比这更清楚的了。
The syntax for declaring and defining constructors in C++ uses the name of the class. There has to be some way of doing that, and using the name of the class is concise, and easy to understand. C# and Java both copied C++'s syntax, presumably because it would be familiar to at least some of the audience they were targeting.
在 C++ 中声明和定义构造函数的语法使用类的名称。必须有某种方法来做到这一点,并且使用类名要简洁易懂。C# 和 Java 都复制了 C++ 的语法,大概是因为至少它们所针对的某些受众会熟悉它。
The precise flow of execution depends what language you're talking about, but what the three you list have in common is that first some memory is assigned from somewhere (perhaps allocated dynamically, perhaps it's some specific region of stack memory or whatever). Then the runtime is responsible for ensuring that the correct constructor or constructors are called in the correct order, for the most-derived class and also base classes. It's up to the implementation how to ensure this happens, but the required effects are defined by each of those languages.
精确的执行流程取决于您所谈论的语言,但是您列出的三种语言的共同点是首先从某处分配一些内存(可能是动态分配的,也许是堆栈内存的某个特定区域或其他什么)。然后运行时负责确保正确的构造函数或构造函数以正确的顺序被调用,对于大多数派生类和基类。如何确保这种情况发生取决于实现,但所需的效果由每种语言定义。
For the simplest possible case in C++, of a class that has no base classes, the compiler simply emits a call to the constructor specified by the code that creates the object, i.e. the constructor that matches any arguments supplied. It gets more complicated once you have a few virtual bases in play.
对于 C++ 中最简单的可能情况,一个没有基类的类,编译器简单地调用由创建对象的代码指定的构造函数,即与提供的任何参数匹配的构造函数。一旦你有几个虚拟基地在玩,它就会变得更加复杂。
回答by user207421
I want to know that why the name of constructor is always same as that of class name
我想知道为什么构造函数的名称总是与类名称相同
So that it can be unambigously identified as the constructor.
这样就可以明确地将其标识为构造函数。
and how its get invoked implicitly when we create object of that class.
以及当我们创建该类的对象时如何隐式调用它。
It is invoked by the compiler because it has already been unambiguously identified because of its naming sheme.
编译器会调用它,因为它的命名模式已经明确标识了它。
Can anyone please explain the flow of execution in such situation?
任何人都可以解释在这种情况下的执行流程吗?
- The new X() operator is called.
- Memory is allocated, or an exception is thrown.
- The constructor is called.
- The new() operator returns to the caller.
- 调用新的 X() 运算符。
- 内存已分配,或抛出异常。
- 构造函数被调用。
- new() 操作符返回给调用者。
the question is why designers decided so?
问题是设计师为何如此决定?
Naming the constructor after its class is a long-established convention dating back at least to the early days of C++ in the early 1980s, possibly to its Simula predecessor.
以类命名构造函数是一个长期建立的约定,至少可以追溯到 1980 年代早期 C++ 的早期,可能是其 Simula 的前身。
回答by Kartik Gautam
The convention for the same name of the constructor as that of the class is for programming ease, constructor chaining, and consistency in the language.
构造函数的名称与类的名称相同的约定是为了便于编程、构造函数链接和语言的一致性。
For example, consider a scenario where you want to use Scanner class, now what if the JAVA developers named the constructor as xyz!
例如,考虑一个你想使用 Scanner 类的场景,现在如果 JAVA 开发人员将构造函数命名为 xyz 怎么办!
Then how will you get to know that you need to write :
那么你将如何知道你需要写:
Scanner scObj = new xyz(System.in) ;
扫描仪 scObj = new xyz(System.in) ;
which could've have been really weird, right! Or, rather you might have to reference a huge manual to check constructor name of each class so as to get object created, which is again meaningless if you could have a solution of the problem by just naming constructors same as that of the class.
这可能真的很奇怪,对吧!或者,您可能必须参考大量手册来检查每个类的构造函数名称,以便创建对象,如果您可以通过仅命名与类的构造函数相同的构造函数来解决问题,这又是毫无意义的。
Secondly, the constructor is itself created by the compiler if you don't explicitly provide it, then what could be the best name for constructor could automatically be chosen by the compiler so it is clear to the programmer! Obviously, the best choice is to keep it the same as that of the class.
其次,构造函数本身是由编译器创建的,如果您没有明确提供它,那么编译器可以自动选择构造函数的最佳名称,因此程序员很清楚!显然,最好的选择是保持与类的相同。
Thirdly, you may have heard of constructor chaining, then while chaining the calls among the constructors, how the compiler will know what name you have given to the constructor of the chained class! Obviously, the solution to the problem is again same, KEEP NAME OF THE CONSTRUCTOR SAME AS THAT OF THE CLASS.
第三,您可能听说过构造函数链接,那么在将构造函数之间的调用链接起来时,编译器如何知道您为链接类的构造函数指定了什么名称!显然,该问题的解决方案还是一样的,保持构造函数的名称与类的名称相同。
When you create the object, you invoke the constructor by calling it in your code with the use of new keyword(and passing arguments if needed) then all superclass constructors are invoked by chaining the calls which finally gives the object.
创建对象时,通过在代码中使用 new 关键字(并在需要时传递参数)调用构造函数来调用构造函数,然后通过链接最终给出对象的调用来调用所有超类构造函数。
Thanks for Asking.
感谢提问。