Java和C ++之间的对象创建的主要区别是什么?

时间:2010-09-29 09:05:17

标签: java c++ object creation

我正准备参加Java考试,之前考试的一个问题是:“Java和C ++之间对象创建的主要区别是什么?”

我想我知道对象创建的基础知识,例如如何调用构造函数以及Java中的初始化块以及当一个类的构造函数调用另一个尚未构造的类的方法时会发生什么,等等,但我找不到任何明显的东西。答案应该是一两句话,所以我不认为Java中整个对象创建过程的描述就是他们想到的。

有什么想法吗?

7 个答案:

答案 0 :(得分:25)

  

Java和C ++之间的对象创建的主要区别是什么?

与Java不同,C ++对象也可以在堆栈上创建。

例如,在C ++中,您可以编写

Class obj; //object created on the stack

在Java中你可以写

Class obj; //obj is just a reference(not an object)
obj = new Class();// obj refers to the object

答案 1 :(得分:19)

除了其他优秀答案之外,还有一件非常重要的事情,通常被忽略/遗忘或误解(这解释了我为何详细介绍了以下流程):

  • 在Java中,方法是虚拟的,即使从构造函数调用(这可能会导致错误)
  • 在C ++中,从构造函数调用虚拟方法时不是虚拟的(这可能会导致误解)

什么?

  • 让我们设想一个基类,使用虚方法foo()。
  • 让我们设想一个Derived类,继承自Base,它会覆盖方法foo()

C ++和Java之间的区别是:

  • 在Java中,从Base类构造函数调用foo()将调用Derived.foo()
  • 在C ++中,从Base类构造函数调用foo()将调用Base.foo()

为什么?

每种语言的“错误”都不同:

  • 在Java中,调用构造函数中的任何方法都可能导致细微的错误,因为重写的虚方法可能会尝试访问在Derived类中声明/初始化的变量。
  

从概念上讲,构造函数的工作是使对象存在(这不是一个普通的壮举)。在任何构造函数中,整个对象可能只是部分形成 - 您只能知道基类对象已经初始化,但您无法知道哪些类是从您继承的。但是,动态绑定的方法调用会在转发层次结构中“前进”或“向外”。它在派生类中调用方法。如果你在构造函数中执行此操作,则调用一个方法可能会操作尚未初始化的成员 - 这是一个确定的灾难处方。

     

Bruce Eckel,http://www.codeguru.com/java/tij/tij0082.shtml

  • 在C ++中,必须记住虚拟将无法按预期工作,因为只会调用当前构造类的方法。原因是避免访问数据成员甚至是尚不存在的方法。
  

在基类构造期间,虚函数永远不会进入派生类。相反,该对象的行为就像它是基本类型一样。非正式地说,在基类构造期间,虚函数不是。

     

Scott Meyers,http://www.artima.com/cppsource/nevercall.html

答案 2 :(得分:8)

除了堆/堆栈问题,我会说:C ++构造函数具有初始化列表,而Java使用赋值。有关详细信息,请参阅http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.6

答案 3 :(得分:4)

我会回答:C ++允许在任何地方创建一个对象:堆,堆栈,成员。 Java强制您在堆上分配对象,始终

答案 4 :(得分:2)

在Java中,执行Java代码的Java虚拟机(JVM)必须可能 1 记录所有正在创建的对象(或者对它们的引用是准确的)所以以后可以通过垃圾收集自动释放为它们分配的内存,而不再引用对象。

编辑:我不确定这是否可归因于严格意义上的对象创建,但在创建和赋值给变量之间肯定会发生,即使没有明确的赋值(当你创建一个对象而不分配它,JVM必须在那之后的一段时间自动释放它,因为没有更多的引用。)

在C ++中,只有在堆栈上创建的对象才会自动释放(当它们超出范围时),除非你使用某种机制来处理这个问题。

1 :取决于JVM的实现。

答案 5 :(得分:1)

C ++和Java中的构造函数之间存在一个主要的设计差异。其他差异来自此设计决定。

主要区别在于JVM在开始执行任何构造函数之前首先将所有成员初始化为零。在C ++中,成员初始化是构造函数的一部分。

结果是在执行基类构造函数期间,在C ++中派生类的成员尚未初始化!在Java中,它们已被零初始化。

因此,在paercebal's answer中解释的规则是,从构造函数调用的虚拟调用不能下降到派生类中。否则可以访问未初始化的成员。

答案 6 :(得分:-1)

假设c ++在进行新调用时使用alloc(),那么它们可能就是这样 寻找。 (我不知道C ++,所以在这里我可能非常错误)

Java的内存模型在需要时分配一块内存,并为它使用的每个新内存分配 这个预先分配的区域。这意味着java中的新东西只是设置指向a的指针 内存段并在C ++中使用新的移动指针(授予它在后台使用malloc) 将导致系统调用。

这使得在Java中创建的对象比使用malloc的语言更便宜; 至少在没有初始化的情况下。

简而言之 - 用Java创建对象很便宜 - 除非你创建它们,否则不要担心它。