一尘不染

Java和C ++在对象创建方面的主要区别是什么?

java

我正在为Java考试做准备,上一次考试中的一个问题是:“ Java和C ++在对象创建方面的主要区别是什么?”

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

有任何想法吗?


阅读 188

收藏
2020-12-03

共1个答案

一尘不染

除了其他出色的答案外,还有一件非常重要的事情,并且通常被忽略/遗忘或被误解(这解释了为什么我在下面详细介绍该过程):

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

什么?

  • 让我们想象一个带有虚拟方法foo()的基类。
  • 让我们想象一个继承自Base的派生类,该类重写方法foo()

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

  • 在Java中,从基类构造函数中调用foo()将调用Derived.foo()
  • 在C ++中,从基类构造函数中调用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

2020-12-03