Javaの最終とC ++のconst


回答:


195

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つの方法のいずれかで実現できます。

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 ++(pre-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異なります。(メンバー関数の1つだけをオンにすることでオーバーロードすることもできconstます。(C ++ 11では、メンバー関数を最終としてマークすることもできます。C++ 11の更新セクションを参照してください)


C ++ 11アップデート:

C ++ 11では、実際には、クラスとメンバー関数の両方をとしてマークすることができます。finalたとえば、Javaの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;
};

constおよびfinalここの順序が必要です)。

以前は、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;を見て、キーワードにするとコードが壊れる理由を確認してください)


3
これらのメソッドを仮想化する必要があります。そうでなければ、あなたは本当に同じことをしていません
BlueRaja-Danny Pflughoeft

1
最後の例では、あなたが持っているものは合法ですが、それfinal int a; a = 10; a = 11;はそうではないことに言及する価値があります(それfinalは変数修飾子としての目的です)。 。
corsiKa 2011年

2
C ++ 0xは、finalまさにこの目的のためにメンバー関数デコレーターを追加することに注意してください。VC ++ 2005、2008、および2010にsealedは、ではなく、contextualキーワードを使用してこれがすでに実装されていますfinal
ildjarn、2011年

@ildjarn-知っておくと面白いですが、私が気付いていなかった比較的小さなC ++ 0xの変更もあります!これはC ++ 0xで変更されていることを示す小さなコメントをテキストのどこかに追加します。
フレキソ

1
どうやら人々はまだ結果としてfinalructor使ってコードベースでまだs / const / final / gを 実行しています!
フレキソ

30

Javaでは、最後のキーワードを次の4つの目的で使用できます。

  • それをシールするクラスまたはメソッド(サブクラスなし/オーバーライドは許可されません)
  • それを宣言するためにメンバー変数でそれは正確に一度だけ設定できることです(私はこれがあなたが話していることだと思います)
  • メソッドで宣言された変数で、正確に1回だけ設定できるようにする
  • メソッド内で変更できないことを宣言するメソッドパラメータ

重要なことの1つは、Javaの最終メンバー変数 1回だけ設定する必要があるということです。たとえば、コンストラクター、フィールド宣言、または初期化子の中です。(ただし、メソッドで最終メンバー変数を設定することはできません)。

メンバー変数をfinalにするもう1つの結果はメモリモデルに関係します。これは、スレッド環境で作業する場合に重要です。


「記憶モデル」とはどういう意味ですか?わかりません。
Tony

1
@Tony:Java言語仕様、第17.4章 メモリモデル- docs.oracle.com/javase/specs/jls/se8/html/index.htmlは -最初のヒットをグーグル
ラルフ・

27

constオブジェクトのみを呼び出すことができるconst方法を、一般的に不変と考えられています。

const Person* person = myself;
person = otherPerson; //Valid... unless we declared it const Person* const!
person->setAge(20); //Invalid, assuming setAge isn't a const method (it shouldn't be)

finalオブジェクトは、新しいオブジェクトに設定されていないが、それは不変ではないことができます-任意の呼び出しから誰かを止めるものは何もないset方法は。

final Person person = myself;
person = otherPerson; //Invalid
person.setAge(20); //Valid!

Javaには、オブジェクトを不変として宣言する固有の方法はありません。自分でクラスを不変として設計する必要があります。

変数がプリミティブ型の場合、final/ constは同じように機能します。

const int a = 10; //C++
final int a = 10; //Java
a = 11; //Invalid in both languages

3
これも素晴らしい答えです(他の多くの記事と同様)。残念ながら、私は1つの回答しか受け入れることができません。:)
WinWin

1
完璧な答えです!
ADJ、

13

Java finalは、プリミティブ値型のC ++ constと同等です。

Java参照型では、最後のキーワードはconstポインターと同等です...すなわち

//java
final int finalInt = 5;
final MyObject finalReference = new MyObject();

//C++
const int constInt = 5;
MyObject * const constPointer = new MyObject();

「最後のキーワードはconstポインタに相当します」
ADJ

8

あなたはここでいくつかの素晴らしい答えをすでに持っていますが、追加する価値があると思われた1つの点:constC ++では、プログラムの他の部分がオブジェクトの状態を変更するのを防ぐために一般的に使用されます。指摘したようにfinal、Javaではこれを行うことができません(プリミティブを除く)- 参照が別のオブジェクトに変更されるのを防ぐだけです。ただし、を使用している場合はCollection、静的メソッドを使用してオブジェクトへの変更を防ぐことができます

 Collection.unmodifiableCollection( myCollection ) 

これは、Collection要素への読み取りアクセスを提供する参照を返しますが、変更が試みられた場合は例外をスローし、constC ++のようになります。


8

Java finalはプリミティブ型と参照でのみ機能し、constキーワードが何かで機能するオブジェクトインスタンス自体では機能しません。

前者const list<int> melist;と比較final List<Integer> melist;すると、リストを変更できなくなりますが、後者では、新しいリストをに割り当てることができませんmelist


3

特定の微妙なマルチスレッドプロパティがあることを除いて、宣言された変数は宣言時finalに初期化する必要はありません!

つまり、これはJavaで有効です。

// declare the variable
final int foo;

{
    // do something...

    // and then initialize the variable
    foo = ...;
}

これは、C ++で記述されている場合は無効ですconst


2

ウィキペディアによると:

  • C ++では、constフィールドは再割り当てから保護されるだけでなく、constメソッドのみを呼び出すことができ、他のメソッドのconst引数としてのみ渡すことができるという追加の制限があります。
  • 非静的内部クラスは、ファイナルであるかどうかに関係なく、包含クラスの任意のフィールドに自由にアクセスできます。

1
「再割り当て」という単語は、そのページの現在のバージョンには表示されません。また、「アクセス」の意味に応じて、2番目の点に似ているものもありません。「非静的インナー」はダブルトークです。ウィキペディアは、C ++やJavaの標準的なリファレンスではありません。
ローンの侯爵

2

constポインタ、つまり定数ポインタと定数オブジェクトへのポインタについて話すと、C ++での意味が複雑になるので、「大雑把に」言っていると思います。Javaにfinalは「明示的な」ポインタがないため、にはこれらの問題はありません。


1

switch / caseステートメントの例で理解したことを説明しましょう。

各caseステートメントの値は、スイッチ値と同じデータ型のコンパイル時の定数値でなければなりません。

以下のようなものを宣言します(メソッド内でローカルインスタンスとして、またはクラス内で静的変数(静的に追加します)またはインスタンス変数として)。

final String color1 = "Red";

そして

static final String color2 = "Green";

switch (myColor) { // myColor is of data type String
    case color1:
    //do something here with Red
    break;
    case color2:
    //do something with Green
    break;
}

color1クラス/インスタンス変数であり、ローカル変数ではない場合、このコードはコンパイルされません。これはcolor1、静的な最終として定義されている場合にコンパイルされます(その後、静的な最終変数になります)。

コンパイルされない場合、次のエラーが発生します

error: constant string expression required

-7

キーワード「const」は、変数がROMに保存されることを意味します(マイクロプロセッサを使用)。コンピューターでは、変数はアセンブリコード用のRAM領域に保存されます(読み取り専用RAM)。これは、変数が書き込み可能RAMにないことを意味します:スタティックメモリ、スタックメモリ、ヒープメモリ。

キーワード「最終」は、変数が書き込み可能なRAMに保存されることを意味しますが、変数が変更されるのは1回だけであることをコンパイラに通知します。

//in java language you can use:
static final int i =10;
i =11; //error is showed here by compiler

//the same in C++ the same as follows
int i =10;
const int &iFinal = i;

iFinal = 11; //error is showed here by compiler the same as above

「const」はパフォーマンスが悪いので、Javaは使用しないと思います。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.