1

このC++プログラムでは、

#include<iostream>
using namespace std;

class Base
{

    public:

    Base()
    {
        cout<<"\n\nBase ctr";
        fun();
    }  

    virtual void fun()
    {
        cout<<"\n\nBase's fun()";
    }
};

class Derived : public Base
{
    public:

    Derived()
    {
        cout<<"\n\nDerived ctr";
        fun();
    }

    virtual void fun()
    {
        cout<<"\n\nDerived's fun()";
    }
};
    int main()
    {
        Derived obj;
        return 0;
    }

Derivedクラスオブジェクトを使用してBaseクラスのコンストラクターから仮想関数を呼び出すと、Baseのクラスfun()が呼び出されます。

出力::
ベースセンター

ベースのfun()

派生ctr

派生のfun()

ここで説明されている理由 が

このJavaプログラムでは、

class Base
{
    Base()
    {
        System.out.println( "\n\nBase ctr" );
        fun();
    }
    void fun()
    {
        System.out.println( "\n\nBase's fun()" );
    }
}

class Derived extends Base
{
    int a=1;

    Derived()
    {
        System.out.println( "\n\nDerived ctr a = "+a );

        a=8;
        fun();
    }

    void fun()
    {
       System.out.println( "\n\nDerived's fun() a = "+a );
    }

    public static void main(String args[])
    {
       Derived obj = new Derived();
    }
}

出力は::
Basectr

派生したfun()a = 0

派生ctra= 1

派生したfun()a = 8

ここでは、派生クラスfun()が呼び出されているため、 c++プログラムに適用される制約はJAVAプログラムには適用されません。なぜ?

4

1 に答える 1

3

2つの言語は、動的ディスパッチに対して異なるアプローチを取ります。C ++では、完全に構築されたオブジェクトにのみディスパッチします。これは、階層コンストラクターのさまざまなレベルが実行を開始するときに、構築中にオブジェクトのタイプを変更することによって処理されます。一方、Javaは、最下位のコンストラクターを開始する前に、オブジェクトが最も派生した型であると見なします。

Javaアプローチの問題は、まだ構築されていないオブジェクトに対して実際にコードを実行している可能性があることです。派生型のフィールドがXに初期化されており、メソッドでアクセス/更新されていることを考慮してください。ベースオブジェクトでそのメソッドを呼び出すと、コンストラクターがメンバーを初期化する前にメンバーにアクセスします。

いずれにせよ、どちらの言語でも、オブジェクトのコンストラクタまたはデストラクタで仮想関数を呼び出さないようにする必要があります。


実例:

public class Base {
   public final int x;
   public Base() { 
      x = foo();
   }
   int foo() { return 1; }
}
public class Derived extends Base {
   public final int y;
   public Derived() {
      y = 2;
   }
   int foo() { return y; }
}
Derived d = new Derived();
assert( d.x == d.y );                      // Can this ever fail?

このコードには、2つのfinalintがあり、コードは十分に単純に思えます。assert失敗することはありますか?

于 2012-05-29T14:25:24.660 に答える