1. ホーム
  2. java

[解決済み] Java の final と C++ の const の比較

2022-04-27 19:01:09

質問

その C++プログラマーのためのJavaチュートリアル と書いてあります(ハイライトは私です)。

<ブロッククオート

キーワードfinalは おおよそ C++のconstと同等

この文脈での "roughly" の意味は何ですか?それは まさに 同じですか?

違いがあるとすれば、それは何ですか?

解決方法は?

C++では、メンバ関数に印をつける const で呼び出される可能性があることを意味します。 const インスタンスを作成します。Javaにはこれに相当するものはない。例.

class Foo {
public:
   void bar();
   void foo() const;
};

void test(const Foo& i) {
   i.foo(); //fine
   i.bar(); //error
}


値は、例えば、Javaのみで、一度、後で割り当てることができます。

public class Foo {
   void bar() {
     final int a;
     a = 10;
   }
}

はJavaでは合法ですが、C++では合法ではありません。

public class Foo {
   void bar() {
     final int a;
     a = 10;
     a = 11; // Not legal, even in Java: a has already been assigned a value.
   }
}


JavaとC++の両方において、メンバ変数が final / const をそれぞれ作成します。これらは、クラスのインスタンスが構築され終わるまでに値を与える必要があります。

Javaでは、コンストラクタが終了する前に設定する必要があります。これは、2つの方法のうちの1つで実現できます。

public class Foo {
   private final int a;
   private final int b = 11;
   public Foo() {
      a = 10;
   }
}

C++では、初期化リストを使って const メンバに値を与えます。

class Foo {
   const int a;
public:
   Foo() : a(10) {
      // Assignment here with = would not be legal
   }
};


Javaでは、finalは物事を上書きできないようにマークするために使用することができます。C++(C++11以前)では、このようなことはありません。例えば

public class Bar {
   public final void foo() {
   }
}

public class Error extends Bar {
   // Error in java, can't override
   public void foo() {
   }
}

でも、C++で。

class Bar {
public:
   virtual void foo() const {
   }
};

class Error: public Bar {
public:
   // Fine in C++
   virtual void foo() const {
   }
};

というのは、メンバ関数をマークするセマンティクスが const が異なります。(また オーバーロード を持つだけで const を片方のメンバ関数に追加します。(C++11では、メンバ関数をfinalとマークすることができることにも注意してください。)


C++11のアップデートです。

C++11では、クラスとメンバ関数の双方に final といったように、Javaの同機能と同一のセマンティクスを持つ。

public class Bar {
   public final void foo() {
   }
}

public class Error extends Bar {
   // Error in java, can't override
   public void foo() {
   }
}

C++11で正確に次のように書けるようになった。

class Bar {
public:
  virtual void foo() final;
};

class Error : public Bar {
public:
  virtual void foo() final;
};

このサンプルは、G++ 4.7のプレリリースでコンパイルする必要がありました。これは const この場合、最も近い等価なC++キーワードでは見られなかったJava的な振る舞いを提供し、むしろそれを補強しています。ですから、もしあなたがあるメンバ関数を finalconst をすることになります。

class Bar {
public:
  virtual void foo() const final;
};

(の順番は constfinal が必要です)。

以前は、直接的に相当する const メンバ関数を作成することはできますが virtual は、コンパイル時にエラーを発生させないとはいえ、可能性のあるオプションです。

同様にJavaも。

public final class Bar {
}

public class Error extends Bar {
}

がC++11になりました。

class Bar final {
};

class Error : public Bar {
};

(以前は private コンストラクタは、おそらくC++でこれに最も近いものだったでしょう)

興味深いことに、C++11以前のコードとの後方互換性を維持するために final はありません。 は通常の方法ではキーワードになります。(些細な、合法的なC++98の例を見てみましょう。 struct final; をキーワードにすると、なぜコードが壊れてしまうのかがわかります)