のC++ プログラマー向け Java チュートリアル次のように述べています(ハイライトは私自身によるものです)。
キーワードfinalはだいたいC++のconstに相当する
この文脈で「だいたい」とはどういう意味でしょうか?その通り同じ?
違いがあるとすれば、それは何でしょうか?
ベストアンサー1
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.
}
}
final
Java と C++ の両方で、メンバー変数はそれぞれ/になりますconst
。クラスのインスタンスの構築が完了するまでに、これらに値を与える必要があります。
Java では、コンストラクターが終了する前に設定する必要があります。これは、次の 2 つの方法のいずれかで実現できます。
public class Foo {
private final int a;
private final int b = 11;
public Foo() {
a = 10;
}
}
const
C++ では、メンバーに値を与えるために初期化リストを使用する必要があります。
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
異なるためです。(また、過負荷メンバー関数の1つだけに を記述しますconst
。(C++11ではメンバー関数をfinalに指定できることにも注意してください。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 のような動作を提供することで拡張されることに注意してください。したがって、メンバー関数を両方にしたい場合はfinal
、const
次のようにします。
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
ない通常の方法でキーワードにします。(struct final;
キーワードにするとコードが壊れる理由を理解するために、単純で合法的な C++98 の例を見てみましょう)