C++継承マスター:再利用可能なコードで強力なクラスを構築
C++継承
このチュートリアルでは、実践的な例を通じてC++の継承について学びます。
継承はC++におけるオブジェクト指向プログラミングの主要機能の一つです。既存のクラス(基底クラス)から新しいクラス(派生クラス)を作成できます。
派生クラスは基底クラスの機能を継承し、独自の追加機能を持つことができます。例えば:
class Animal {
// eat()関数
// sleep()関数
};
class Dog : public Animal {
// bark()関数
};
ここでは、DogクラスがAnimalクラスから派生しています。DogがAnimalから派生しているため、AnimalのメンバはDogからアクセス可能です。

publicキーワードを使ってDogをAnimalから継承していることに注目してください。
class Dog : public Animal {...};
privateやprotectedキーワードをpublicの代わりに使うこともできます。これらの違いについては後で学びます。
is-a関係
継承はis-a関係です。2つのクラス間にis-a関係がある場合のみ継承を使用します。
例:
- 車は乗り物である
- オレンジは果物である
- 外科医は医者である
- 犬は動物である
例1: C++継承のシンプルな例
// 継承を示すC++プログラム
#include <iostream>
using namespace std;
// 基底クラス
class Animal {
public:
void eat() {
cout << "I can eat!" << endl;
}
void sleep() {
cout << "I can sleep!" << endl;
}
};
// 派生クラス
class Dog : public Animal {
public:
void bark() {
cout << "I can bark! Woof woof!!" << endl;
}
};
int main() {
// Dogクラスのオブジェクトを作成
Dog dog1;
// 基底クラスのメンバを呼び出し
dog1.eat();
dog1.sleep();
// 派生クラスのメンバを呼び出し
dog1.bark();
return 0;
}
出力
I can eat! I can sleep! I can bark! Woof woof!!
ここでは、dog1(派生クラスDogのオブジェクト)が基底クラスAnimalのメンバにアクセスできます。これはDogがAnimalから継承されているためです。
// Animalクラスのメンバを呼び出し
dog1.eat();
dog1.sleep();
C++ protectedメンバ
アクセス修飾子protectedはC++継承において特に重要です。
privateメンバと同様、protectedメンバはクラス外部からアクセスできません。しかし、**派生クラス**と**フレンドクラス/関数**からはアクセス可能です。
クラスのデータを隠蔽しつつ、派生クラスに継承させたい場合にprotectedメンバが必要です。
詳細はC++アクセス修飾子チュートリアルを参照してください。
例2: C++ protectedメンバ
// protectedメンバを示すC++プログラム
#include <iostream>
#include <string>
using namespace std;
// 基底クラス
class Animal {
private:
string color;
protected:
string type;
public:
void eat() {
cout << "I can eat!" << endl;
}
void sleep() {
cout << "I can sleep!" << endl;
}
void setColor(string clr) {
color = clr;
}
string getColor() {
return color;
}
};
// 派生クラス
class Dog : public Animal {
public:
void setType(string tp) {
type = tp;
}
void displayInfo(string c) {
cout << "I am a " << type << endl;
cout << "My color is " << c << endl;
}
void bark() {
cout << "I can bark! Woof woof!!" << endl;
}
};
int main() {
// Dogクラスのオブジェクトを作成
Dog dog1;
// 基底クラスのメンバを呼び出し
dog1.eat();
dog1.sleep();
dog1.setColor("black");
// 派生クラスのメンバを呼び出し
dog1.bark();
dog1.setType("mammal");
// dog1のgetColor()を引数として使用
// getColor()はstringデータを返す
dog1.displayInfo(dog1.getColor());
return 0;
}
出力
I can eat! I can sleep! I can bark! Woof woof!! I am a mammal My color is black
ここでは、変数typeがprotectedであり、派生クラスDogからアクセス可能です。DogクラスのsetType()関数でtypeを初期化していることからわかります。
一方、private変数colorはDogで初期化できません。
class Dog : public Animal {
public:
void setColor(string clr) {
// エラー: メンバ "Animal::color" はアクセス不可
color = clr;
}
};
また、protectedキーワードはデータを隠蔽するため、DogやAnimalクラスのオブジェクトから直接typeにアクセスすることはできません。
// エラー: メンバ "Animal::type" はアクセス不可
dog1.type = "mammal";
C++継承のアクセスモード
前回のチュートリアルで、public、private、protectedなどのC++アクセス指定子について学びました。
これまで、既存の基底クラスからクラスを派生させるためにpublicキーワードを使ってきました。しかし、privateやprotectedキーワードを使ってクラスを派生させることもできます。例えば:
class Animal { /* コード */ };
class Dog : private Animal { /* コード */ };
class Cat : protected Animal { /* コード */ };
クラスを派生させるこれら様々な方法をアクセスモードと呼びます。これらのアクセスモードには以下の効果があります:
- public: 派生クラスが
publicモードで宣言されている場合、基底クラスのメンバはそのまま派生クラスに継承されます。 - private: この場合、基底クラスのすべてのメンバが派生クラスで
privateメンバになります。 - protected: 基底クラスの
publicメンバが派生クラスでprotectedメンバになります。
基底クラスのprivateメンバは、派生クラスでも常にprivateです。
詳細はC++ public、private、protected継承チュートリアルを参照してください。
継承におけるメンバ関数のオーバーライド
基底クラスと派生クラスが同じ名前と引数を持つメンバ関数を持つとします。
派生クラスのオブジェクトを作成してそのメンバ関数にアクセスしようとすると、基底クラスのものではなく派生クラスのメンバ関数が呼び出されます。
派生クラスのメンバ関数が基底クラスのメンバ関数をオーバーライドします。
詳細はC++関数オーバーライドを参照してください。
推奨リーディング: C++多重継承
C言語
- C# static キーワード:静的変数、メソッド、クラスをマスターする
- C# 入れ子クラスを理解する:定義、使用法、継承
- C++演算子完全ガイド:算術・代入・関係・論理・ビット演算子と実例
- C++クラスとオブジェクト完全ガイド:オブジェクト指向プログラミングの実践
- C++ public/protected/private継承の違いを徹底解説
- C++クラステンプレート完全ガイド:実践的なジェネリックプログラミング
- C++ストレージクラス完全解説:スコープ、ライフタイム、使い方
- C++ポリモーフィズム完全理解:仮想関数と純粋仮想関数
- C++データ抽象化完全マスター:インターフェースと実装の分離
- C++データカプセル化:コードを守る仕組みと実装例
- Python継承マスター:概念、構文、実践例