
「C++言語」の「継承」の仕組みを身に付けよう!
これまで「クラス」の作り方や使い方について学んできましたが、今回はクラスに「親子関係」を作ることができる「継承」について勉強していきます。
ですが、「継承」については以前に少し学んだことがあって、難しくて理解ができなかったので、ちょっとずつ学んでいきたいと思います。
まだこの先に学ぶ内容がわからないのですが、たぶん「C++言語学習」では、ここが「山場」になるような気がしています。
「クラスの親子関係」を作る「継承」の仕組みとは?
これまで学んできたクラスはそれぞれが「独立」して存在しているため、何も関係性がありませんでした。
クラスに「親子関係」を作ることで、「プログラムの重複を減らす」ことができ、「プログラムの変更も行いやすくなる」という利点があるみたいなので、さっそく「継承」について学んでいきましょう。
今回は、「自転車(Bicycle)」を元にさまざまなクラスの作成に取り組んでみたいと思います。
他にも、「電動自転車(ElectricBicycle)」や、「マウンテンバイク(MountainBike)」クラスを作ってみたいと思います。
これらのクラスに「親子関係」を作ることで、「継承の仕組み」を作っていきます。
まず、「親(基底)」となる「Bicycle」クラスを作っていきたいと思いますが、どのような内容にするかをいろいろと考えていました。
「基底クラス」を作る
これから作るクラスの関係は、

のようになります。
「Bicycle」クラスが持っている「メンバ」と「メンバ関数」は、
- speed
- 自転車の速さ
- getSpeed()
- 「自転車の速さ」を取得するゲッター
- forward()
- 前へ進む
- brake()
- 減速する
のようにしたいと思います。
「Bicycle」クラスを作ってみると、まず、「ヘッダーファイル」は、
#ifndef ___CLASS_Bicycle
#define ___CLASS_Bicycle
class Bicycle {
protected:
int speed; // 現在の速度
public:
Bicycle(); // コンストラクタ
int getSpeed(); // 現在の速度を取得するゲッター
void forward(int increaseSpeed); // 前へ進む
void brake(); // ブレーキを掛ける
};
#endif
そして、「実装ファイル」は次のようになります。
#include <iostream>
#include "Bicycle.h"
// コンストラクタ
Bicycle::Bicycle(){
speed = 0;
}
// 現在の速度を取得するゲッター
int Bicycle::getSpeed(){
return speed;
}
// 前へ進む
void Bicycle::forward(int increaseSpeed){
speed += increaseSpeed;
}
// ブレーキを掛ける
void Bicycle::brake(){
if( speed > 0){
speed -= 1;
}
}
もっといろいろな機能を実装できそうですが、自分の頭では把握ができなくなりそうなので、今回はかなりシンプルな構成のクラスを作りました。
このクラスは「継承される元となるクラス」なのですが、「C++言語」では「基底クラス」と呼ばれているそうです。
「派生クラス」を作る
継承される「ElectricBicycle」クラスの「ヘッダーファイル」は、
#ifndef ___CLASS_ElectricBicycle
#define ___CLASS_ElectricBicycle
#include "Bicycle.h"
class ElectricBicycle : public Bicycle {
public:
void motorAssistForward(); //「モーターアシスト」を使った前進
};
#endif
のようになります。
電動自転車なので、「モーターアシストを使った前進機能」を作成してみました。
このクラスの「実装ファイル」は、
#include <iostream>
#include "ElectricBicycle.h"
//「モーターアシスト」を使った前進
void ElectricBicycle::motorAssistForward(){
forward(3);
}
のように作ってみました。
そして、「MountainBike」クラスの「ヘッダーファイル」は、
#ifndef ___CLASS_MountainBike
#define ___CLASS_MountainBike
#include "ElectricBicycle.h"
class MountainBike : public Bicycle {
public:
void gearForward(); // 変速ギアを利用して前進
};
#endif
のようになり、マウンテンバイクなので、「変速ギアを利用した前進機能」を作ってみました。
「実装ファイル」の内容は、
#include <iostream>
#include "MountainBike.h"
// 変速ギアを利用して前進
void MountainBike::gearForward(){
forward(5);
}
のようになります。
このように「継承されるクラス」のことは「派生クラス」と呼ぶそうです。
「継承関係」の作り方
「C++言語」の継承関係には「3つ」の種類があり、
- private
- proctected
- public
の3つの継承によって、「基底クラス」のメンバの公開範囲が異なるとのことでした。
まず、クラスに「継承関係」を作るためには、
class 継承するクラス : 継承の種類 基底クラス {
// メンバ
}
のように「ヘッダーファイル」に書くことで、継承関係を作ることができます。
「private」の場合は、「派生クラス」から「基底クラス」の非公開のメンバにはアクセスができないとのことでした。
これはなんとなくわかるかも。
「proctected」の場合は、「基底クラス」の「public」「protected」は「派生クラス」では、「protected」として扱われるとのことでした。
「public」の場合は、「基底クラス」の「private」メンバ以外は、「派生クラス」でも「基底クラスと同様の扱い」になるとのことでした。
メンバの扱い方が継承方法で変化するところがなんか複雑ですね・・・
そもそも、「継承」を使う理由は、「基底クラス(親クラス)」の「メンバ・メンバ関数」を「派生クラス」でも使えるようにすることにあります。
これまでに作ったクラスを実行する「main」関数を作って実行してみると、
#include <iostream>
#include <string>
#include "ElectricBicycle.h"
#include "MountainBike.h"
using namespace std;
int main() {
// 「ElectricBicycle」クラス
ElectricBicycle eb;
eb.motorAssistForward();
cout << "「ElectricBicycle」のスピード=" << eb.getSpeed() << endl;
// 「MountainBike」クラス
MountainBike mb;
mb.gearForward();
cout << "「MountainBike」のスピード=" << mb.getSpeed() << endl;
return 0;
}
のようになります。
このプログラムを実行すると、
「ElectricBicycle」のスピード=3 「MountainBike」のスピード=5
のように表示されます。
「motorAssistForward」関数と「gearForward」関数の中では、「基底クラス」の「Bicycle」クラスで定義されている「forward」関数を使って、「speed」の値を増やしています。

このように「派生クラス」で「基底クラス」のメンバを利用することができるのが「継承」の仕組みです。
まだなんとなくしか理解できていないところもありますが、これまでより「継承」の考え方が理解できてきたような気がします。
でも、積極的にどんどん使っていくことはまだ難しいので、さらにいろいろなクラスを作り、クラスの使い方を身に付けていきたいと思います。
→(前へ)「C言語」の「デストラクタ・インライン関数・静的メンバ」を勉強しよう!