リンドくん
たなべ先生、C++で「継承」と「ポリモーフィズム」っていう言葉をよく聞くんですけど、なんだか難しそうで...
たなべ
確かに専門用語だと難しく感じるよね。
簡単にいえば、継承は「親から子へ特徴を受け継ぐ」、ポリモーフィズムは「同じ名前でも中身が違う」っていう、身近な概念なんだよ。
C++を学んでいると、必ず出会う「継承(inheritance)」と「ポリモーフィズム(polymorphism)」という概念。
これらはオブジェクト指向プログラミングの核心とも言える重要な仕組みです。
一見難しそうに見えるかもしれませんが、実際には私たちの日常生活にも似たような概念が存在しているんです。
例えば、動物という大きなカテゴリから犬や猫が派生し、それぞれが独自の鳴き方を持っているように、プログラムでも基本的なクラスから特化したクラスを作り、それぞれが独自の動作を持てるのです。
この記事では、C++の継承とポリモーフィズムについて、基本概念から実践的な使い方まで、初心者の方でも理解できるよう段階的に解説していきます。
HackATAは、エンジニアを目指す方のためのプログラミング学習コーチングサービスです。 経験豊富な現役エンジニアがあなたの学習をサポートします。
✓ 質問し放題
✓ β版公開中(2025年内の特別割引)
リンドくん
継承って具体的にはどういうことなんですか?
たなべ
簡単に言うと、既存のクラスの特徴を引き継いで新しいクラスを作る仕組みなんだ。
例えば「動物」クラスから「犬」クラスを作る感じだね。
継承(inheritance)とは、既存のクラス(親クラス、基底クラス)の機能を受け継いで、新しいクラス(子クラス、派生クラス)を作成する仕組みです。
この仕組みにより、コードの再利用性が大幅に向上し、保守性の高いプログラムを作ることができます。
継承の最大のメリットは以下の通りです。
まずは、シンプルな継承の例を見てみましょう。
この例では、Animal
クラスが基底クラス、Dog
クラスが派生クラスになっています。
Dog
クラスはAnimal
クラスの機能(sleep()
、eat()
など)をすべて受け継ぎつつ、犬特有の機能(bark()
、wagTail()
)を追加しています。
継承において重要なのがアクセス指定子の理解です。
上の例でname
とage
をprotected
にしているのは、派生クラス(Dog
)からもアクセスできるようにするためです。
もしprivate
にしてしまうと、派生クラスからアクセスできなくなってしまいます。
リンドくん
ポリモーフィズムって何ですか?名前からして難しそう...
たなべ
ポリモーフィズムは「多態性」とも呼ばれるんだ。同じ関数名でも、オブジェクトの種類によって違う動作をする仕組みなんだよ。
これがvirtual関数で実現できるんだ。
ポリモーフィズム(多態性)とは、同じインターフェースを持ちながら、オブジェクトの実際の型に応じて異なる動作をする仕組みです。
これにより、柔軟で拡張性の高いプログラムを作ることができます。
C++ではvirtual関数を使ってポリモーフィズムを実現します。
virtual関数を使うことで、実行時にオブジェクトの実際の型を判断し、適切な関数を呼び出すことができます。
先ほどの動物の例を拡張して、ポリモーフィズムを実装してみましょう。
ここからがポリモーフィズムの真骨頂です。
異なる動物たちを同じ方法で扱えるようになります。
このコードを実行すると、以下のような出力が得られます。
重要なのは、ループの中で同じコード(animal->makeSound()
、animal->move()
)を書いているにも関わらず、それぞれの動物に応じた異なる動作が実行されていることです。これがポリモーフィズムの威力なのです。
ここからは純粋仮想関数(virtual 関数名() = 0;
)について詳しく見てみましょう。
純粋仮想関数を持つクラスは抽象クラスと呼ばれ、直接インスタンス化することができません。
抽象クラスを使うことで、派生クラスが必ず実装すべき機能を強制できます。
これにより、設計者の意図を明確に示し、実装漏れを防ぐことができます。
リンドくん
継承とポリモーフィズム、だんだん分かってきました!でも、使う時に気をつけることはありますか?
たなべ
使い方を間違えると複雑になりすぎることもあるんだ。
いくつかの重要なポイントを押さえておこう。
1. "is-a"関係を意識する
継承は「AはBの一種である」という関係の時に使います。
例えば、「犬は動物の一種である」は自然ですが、「車は道路の一種である」は不自然ですよね。
2. 仮想デストラクタを忘れずに
基底クラスのポインタで派生クラスのオブジェクトを削除する場合、仮想デストラクタが必要です。
3. override キーワードの活用
C++11以降では、override
キーワードを使って意図を明確にしましょう。
仮想関数には若干のオーバーヘッドがあります。しかし、現代のコンパイラは非常に賢く、多くの場合で最適化してくれます。
premature optimization(早すぎる最適化)は避け、まずは設計の清潔さを重視しましょう。
リンドくん
継承とポリモーフィズム、最初は難しく感じましたが、実例を見ると分かりやすいですね!
たなべ
そうだね!概念を理解して実際にコードを書いてみることが一番の学習方法だよ。
最初は簡単な例から始めて、だんだん複雑なものに挑戦していこう。
C++の継承とポリモーフィズムは、オブジェクト指向プログラミングの核心的な概念です。
これらを理解することで、より柔軟で保守性の高いプログラムを作成できるようになります。
プログラミングの学習は、概念を理解するだけでなく、実際に手を動かして体験することが最も重要です。
今回の例を参考に、ぜひ自分なりのクラス設計に挑戦してみてください。