21

私は Java の試験の準備をしていますが、以前の試験で出題された問題の 1 つは、「Java と C++ のオブジェクト作成における主な違いは何ですか?」というものでした。

たとえば、コンストラクターの呼び出し方法やJavaでの初期化ブロックの動作、あるクラスのコンストラクターがまだ構築されていない別のクラスのメソッドを呼び出すとどうなるかなど、オブジェクト作成の基本を知っていると思いますが、できます明らかなことは何も見つかりません。答えは 1 ~ 2 文であるはずなので、Java でのオブジェクト作成プロセス全体の記述は、彼らが考えていたものではないと思います。

何か案は?

4

7 に答える 7

29

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
于 2010-09-29T09:08:26.243 に答える
20

他の優れた回答に加えて、非常に重要であり、通常は無視/忘れられたり、誤解されたりすることが1つあります(これが、以下のプロセスを詳しく説明する理由を説明しています):

  • Java では、コンストラクターから呼び出された場合でも、メソッドは仮想です (バグにつながる可能性があります)。
  • C++ では、仮想メソッドはコンストラクターから呼び出されたときに仮想ではありません (誤解を招く可能性があります)。

何?

  • 仮想メソッド foo() を持つ基本クラスを想像してみましょう。
  • ベースから継承し、メソッド foo() をオーバーライドする派生クラスを想像してみましょう。

C++ と Java の違いは次のとおりです。

  • Java では、基本クラスのコンストラクターから foo() を呼び出すと、Derived.foo() が呼び出されます。
  • C++ では、Base クラスのコンストラクターから foo() を呼び出すと、Base.foo() が呼び出されます。

なんで?

各言語の「バグ」は異なります。

  • Java では、オーバーライドされた仮想メソッドが派生クラスで宣言/初期化された変数にアクセスしようとする可能性があるため、コンストラクターで任意のメソッドを呼び出すと、微妙なバグが発生する可能性があります。

概念的には、コンストラクターの仕事はオブジェクトを存在させることです (これは通常の偉業ではありません)。コンストラクター内では、オブジェクト全体が部分的にしか形成されていない可能性があります。基本クラスのオブジェクトが初期化されたことだけを知ることができますが、どのクラスが自分から継承されているかを知ることはできません。ただし、動的にバインドされたメソッド呼び出しは、継承階層の「前方」または「外側」に到達します。派生クラスのメソッドを呼び出します。コンストラクター内でこれを行うと、まだ初期化されていないメンバーを操作する可能性のあるメソッドを呼び出すことになります。

ブルース・エッケル、http://www.codeguru.com/java/tij/tij0082.shtml

  • C++ では、現在構築されているクラスのメソッドのみが呼び出されるため、仮想は期待どおりに機能しないことを覚えておく必要があります。その理由は、データ メンバーやまだ存在しないメソッドへのアクセスを避けるためです。

基本クラスの構築中に、仮想関数が派生クラスに分類されることはありません。代わりに、オブジェクトは基本型であるかのように動作します。非公式に言えば、基本クラスの構築中、仮想関数はそうではありません。

スコット・マイヤーズ、http://www.artima.com/cppsource/nevercall.html

于 2010-09-29T09:52:14.500 に答える
8

ヒープ/スタックの問題に加えて、C++ コンストラクターには初期化リストがあり、Java は代入を使用します。詳細については、 http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.6を参照してください。

于 2010-09-29T09:24:35.390 に答える
4

私は答えます: C++ では、ヒープ、スタック、メンバーなど、どこでもオブジェクトを作成できます。Java では、常にヒープにオブジェクトを割り当てる必要があります。

于 2010-09-29T09:09:08.833 に答える
2

Java では、Java コードを実行する Java 仮想マシン (JVM) は、作成のすべてのオブジェクト (または正確にはそれらへの参照) をログに記録する必要があります。もう参照されません。

編集:これが厳密な意味でのオブジェクトの作成に起因するかどうかはわかりませんが、明示的な割り当てがなくても、作成と変数への割り当ての間に必ず発生します(オブジェクトを割り当てずに作成すると、JVM はそれ以上参照がないため、しばらくしてから自動解放します)。

C++ では、スタック上に作成されたオブジェクトのみが (スコープ外になったときに) 自動的に解放されますが、これを処理する何らかのメカニズムを使用する必要はありません。

1 : JVM の実装に依存します。

于 2010-09-29T09:28:13.403 に答える
1

C++ と Java のコンストラクターには、主な設計上の違いが 1 つあります。この設計上の決定から、他の違いが生じます。

主な違いは、コンストラクターの実行を開始する前に、JVM が最初にすべてのメンバーをゼロに初期化することです。C++ では、メンバーの初期化はコンストラクターの一部です。

その結果、基本クラス コンストラクターの実行中に、C++ では派生クラスのメンバーがまだ初期化されていません。Java では、これらはゼロで初期化されています。

したがって、paercebal's answerで説明されているルールは、コンストラクターから呼び出された仮想呼び出しは派生クラスに降りることができないというものです。そうしないと、初期化されていないメンバーにアクセスできます。

于 2010-09-29T11:49:09.837 に答える
-1

新しい呼び出しが行われたときに c++ が alloc() を使用すると仮定すると、それが彼らが探しているものかもしれません。(私は C++ を知らないので、ここでは非常に間違っている可能性があります)

Java のメモリ モデルは、必要に応じてメモリのチャンクを割り当て、新しいメモリごとに、事前に割り当てられたこの領域を使用します。これは、Java の new はメモリ セグメントへのポインタを設定し、フリー ポインタを移動するだけであり、C++ の new (バックグラウンドで malloc を使用する場合) はシステム コールになることを意味します。

これにより、malloc を使用する言語よりも Java でオブジェクトを作成する方が安価になります。少なくとも初期化が発生していない場合。

要するに、Java でオブジェクトを作成するのは安価です。大量にオブジェクトを作成しない限り、心配する必要はありません。

于 2010-09-29T12:08:20.793 に答える