【比較解説】C++とJavaでデフォルトの仮想動作はどう違う?
ポリモーフィズム(多態性)を実現する「仮想関数」の扱いは、C++とJavaで大きく異なります。この違いを理解することは、両言語を使いこなす上で非常に重要です。
C++の場合:デフォルトは非仮想
C++では、クラスのメンバー関数はデフォルトで非仮想(non-virtual)です。これは、動的ディスパッチのオーバーヘッドを避け、パフォーマンスを優先する設計思想によるものです。仮想関数として動作させたい場合は、virtualキーワードを明示的に指定する必要があります。
class Base {
public:
virtual void display_msg() { // 明示的に virtual を指定
std::cout << "Base class の display_msg" << std::endl;
}
};
Javaの場合:デフォルトは仮想
一方、Javaではすべてのインスタンスメソッドがデフォルトで仮想(virtual)です。そのため、サブクラスで自由にオーバーライドできます。逆に、オーバーライドを禁止して非仮想にしたい場合は、finalキーワードを使用します。
public void display_msg() { ... } // 仮想(オーバーライド可能)
public final void display_msg() { ... } // 非仮想(オーバーライド不可)
Javaのコード例
class base_class{
public void display_msg(){
System.out.println("The display_msg method of base class");
}
}
class derived_class extends base_class{
public void display_msg(){
System.out.println("The display_msg of derived class called");
}
}
public class Main{
public static void main(String[] args){
base_class my_instance = new base_class();
my_instance.display_msg();
}
}
出力
The display_msg method of base class
コードの解説
まず、display_msgというメソッドを持つ基底クラス「base_class」を作成します。このメソッドは、関連するメッセージを表示するだけのシンプルなものです。
次に、extendsキーワードを使って「base_class」を継承した派生クラス「derived_class」を定義します。このクラスでも同名のdisplay_msgメソッドをオーバーライドしています。
mainメソッドを持つ「Main」クラスでは、base_classのインスタンスを生成し、そこからdisplay_msgを呼び出しています。ここでは基底クラス自身のインスタンスを生成しているため、基底クラス側のメソッドが出力されます。
もしbase_class my_instance = new derived_class();のように派生クラスのインスタンスを基底型の変数に代入すれば、Javaのメソッドはデフォルトで仮想であるため、派生クラス側のメソッドが呼び出される点に注目してください。これがJavaにおける動的ディスパッチの基本的な挙動です。
まとめ:C++とJavaの比較表
| 項目 | C++ | Java |
|---|---|---|
| デフォルトの動作 | 非仮想(non-virtual) | 仮想(virtual) |
| 仮想にする方法 | virtualキーワードを指定 | 何もしない(デフォルト) |
| 非仮想にする方法 | 何もしない(デフォルト) | finalキーワードを指定 |
このように、C++は「明示的に仮想にする」設計、Javaは「明示的に非仮想にする」設計となっており、それぞれの言語の設計哲学(パフォーマンス重視か、柔軟性・拡張性重視か)が反映されています。
-
Javaのデフォルトメソッドで菱形継承問題(ダイアモンド問題)を解決する方法
継承とは継承とは、あるクラスが別のクラスのプロパティやメソッドを受け継ぐ、クラス間の関係のことです。Javaでは「extends」キーワードを使って、次のように定義します。public class A extends B{ }性質を引き継ぐ側のクラスをサブクラス(子クラス)、引き継がれる側のクラスをスーパークラス(親クラス)と呼びます。継承が行われると、スーパークラスのメンバーのコピーがサブクラスのオブジェクト内に作られます。そのため、サブクラスのオブジェクトを使えば、親クラスと子クラスの両方のメンバーにアクセスできます。多重継承とは継承には、単一継承、多段継承、階層継承、多重継承、ハイブリッ
-
Javaのデフォルトメソッドを使ってダイヤモンド問題を解決する方法
継承(Inheritance)とは 継承とは、あるクラスが別のクラスの性質(プロパティやメソッド)を受け継ぐ、2つのクラス間の関係のことです。この関係は extends キーワードを使って次のように定義します。 public class A extends B{ } 性質を受け継ぐ側のクラスは「サブクラス(子クラス)」、受け継がれる側のクラスは「スーパークラス(親クラス)」と呼ばれます。 継承が行われると、スーパークラスのメンバーのコピーがサブクラスのオブジェクト内に作成されます。そのため、サブクラスのオブジェクトを使えば、親クラスと子クラスの両方のメンバーにアクセスすることが可能です。 多重