C/C++プログラミング · 4 min read · Oct 10, 2025
C/C++を段階的に学ぶ - ページ 14
14. 段階的C/C++ — C++プログラミング - 継承
継承
| | はじめに
派生クラスと基底クラス
派生クラスの指定
派生クラスのコンストラクタ
アクセス指定子
パブリック
プライベート
プロテクト
継承なしのアクセス指定子
プロテクトアクセス指定子
アクセス指定子のスコープ
継承を伴うアクセス指定子
継承の種類
単一継承
多重継承
多層継承
ハイブリッド継承
階層継承 |
はじめに
継承はオブジェクト指向プログラミングの最も強力な機能です。継承は、既存のクラスまたは基底クラスから派生クラスと呼ばれる新しいクラスを作成するプロセスです。派生クラスは基底クラスのすべての機能を継承しますが、自身の装飾や洗練を追加できます。
派生クラスと呼ばれるクラスは、基底クラスと呼ばれる別のクラスの特徴を継承できます。
基底クラスの特性を派生クラスに継承することを継承と呼びます .
その名詞は遺産です。私たちは日常生活の中で、クラスがサブクラスに派生する概念を使用しています。例えば、車両はクラスであり、再び自転車、バイク、オート、トラック、バスなどに分かれています。
ここで車両は基底クラスと呼ばれ、派生アイテムは派生クラスまたはサブクラスと呼ばれます。 **
一般的に、すべての基底クラスには特性と機能のリストがあります。この継承の主なテーマは、基底クラスのすべての共通の特性を派生クラスに共有することです。
| |
|
継承には再利用性を許可する重要な機能があります。再利用性の一つの結果は、クラスライブラリの配布の容易さです。プログラマーは、他の人や会社が作成したクラスを使用し、それを変更することなく、特定の状況に適した他のクラスを派生させることができます。
派生クラスと基底クラス
派生クラスと呼ばれるクラスは、基底クラスと呼ばれる別のクラスの特徴を継承できます。
派生クラスは自身の他の機能を追加できるため、基底クラスの専門的なバージョンになります。継承は、既存のクラスの機能を拡張し、階層的な関係を使用してプログラムを設計するための強力な方法を提供します。
派生クラスからの基底クラスメンバーへのアクセスや、派生クラスのオブジェクトからのアクセスは重要な問題です。派生クラスのオブジェクトは、基底クラスのデータや関数にアクセスできますが、キーワードprotectedで前置されているものにはアクセスできません。クラスは基底クラスから公開またはプライベートに派生することができます。
公開派生クラスのオブジェクトは基底クラスのパブリックメンバーにアクセスできますが、プライベート派生クラスのオブジェクトはアクセスできません。
図は派生クラスがどのように継承するかを示しています。
| |
|
クラスは複数の基底クラスから派生することができます。
これを多重継承と呼びます。
クラスは他のクラスの中に含まれることもできます。
派生クラスの指定
クラス宣言はキーワードclassを使用することで非常に簡単であり、派生クラスの宣言も簡単ですが、クラスは基底クラスのIDとアクセス指定子で終了する必要があります。
派生クラスを宣言するための構文:
Class
例えば、class result : public stud;
| | / 学生記録を受け入れて表示するプログラム /
#include
using namespace std;
class add
{
private :
char str[20];
char city[20];
int pin;
public :
void get_add()
{
cout << “住所を入力してください street,city,pin”;
cin >> street >>city>>pin;
}
void put_data()
{
cout << “住所は “ << str
<
};
class stud : public add
{
private :
int sno;
char name[20];
int m1,m2,m3;
public :
void get_data()
{
cout << “学生番号を入力してください “; cin >> sno;
cout << “学生名を入力してください “; cin >> name;
cout << “学生の3科目の成績を入力してください “;
cin >> m1 << m2 << m3;
}
void put_data()
{
cout << “学生番号 :” << sno;
cout << “学生名 :” << name;
cout << “学生の成績 :” << m1 << “ “ <
};
int main()
{
stud s;
s.get_add();
s.get_data();
s.put_add();
s.put_data();
return 0;
} |
上記プログラムの図解説明
| |
|
派生クラスのコンストラクタ
クラスが自身のコンストラクタで宣言されている場合、それは別のクラスの基底クラスです。派生クラスも自身のコンストラクタを持っています。
オブジェクトが宣言されると、どのコンストラクタが実行されますか?
疑いなく、派生クラスのコンストラクタが実行されます。
基底クラスのコンストラクタまたは両方の派生クラスと基底クラスのコンストラクタを実行したい場合は、単に派生クラスのコンストラクタ内で基底クラスのコンストラクタを呼び出します。
| | / 派生クラスのコンストラクタ /
#include
using namespace std;
class Add
{
protected : // 注意 : プライベートではない
unsigned int a;
public :
Add() { a = 0; } // コンストラクタ , 引数なし
Add( int c ) { a = c; } // コンストラクタ , 引数1つ
int get_val(){ return a; } // Aの値を返す
Add operator ++ () // カウントをインクリメント
{
a++; // カウントをインクリメントし、返す
return Add(a); // このカウントに初期化された名前のない一時オブジェクト
} //
};
class Sub : public Add
{
public:
Sub() : Add() { } // コンストラクタ, 引数なし
Sub(int c) : Add(c) { } // コンストラクタ, 引数1つ
Sub operator – () // Aの値をデクリメントし、返す
{ // 名前のない一時オブジェクト
a–; // この値に初期化
return Sub(a);
}
};
int main()
{
Sub ob1; // クラスSub
Sub ob2(100);
cout << “\nOb1 =” << ob1.get_val(); // 表示
cout << “\nOb2 =” << ob2.get_val(); // 表示
ob1++; ob1++; ob1++; // ob1をインクリメント
cout << “\nOb1 =” << ob1.get_val(); // 表示
ob2–; ob2–; // ob2をデクリメント
cout << “\nOb2 =” << ob2.get_val(); // 表示
Sub ob3=ob2–; // ob2からob3を作成
cout << “\nOb3 =” << ob3.get_val(); // 表示
return 0;
} |
アクセス指定子
アクセス指定子は、データとメンバ関数の両方を制御し、隠し、保護するために使用されます。 アクセス指定子は3種類あります。
- パブリックアクセス指定子
- プライベートアクセス指定子
- プロテクトアクセス指定子。
パブリック :
| | メンバーまたはデータがパブリックである場合、クラス内およびその派生クラス内の任意の関数によって使用できます。
C++では、structまたはunionのメンバーはデフォルトでパブリックです。
クラスのパブリックメンバーは、クラスが公開で継承されるときに派生クラスに継承されますが、メンバ関数は(プライベートに)継承されません。 |
プライベート :
| | メンバ関数とそのクラスで宣言された友人のみが使用できます。
クラスのメンバーはデフォルトでプライベートです。
クラスのプライベートメンバーは、基底クラスが公開またはプライベートで継承されるときに派生クラスに継承されません。必要な場合は、これらの値を返すメンバ関数を書く必要があります。 |
プロテクト :
| | プライベートと同様にアクセスされますが、追加として、メンバは宣言されたクラスから派生したクラスのメンバ関数や友人によって使用できますが、派生型のオブジェクトでは使用できません。
クラスのプロテクトメンバーは、次の派生クラスにのみ継承されます。しかし、後のクラスには継承されません。 |
継承なしのアクセス指定子
| |
|
プロテクトアクセス指定子についての詳細
クラスを変更することなく機能を提供します。 プロテクトは自身と派生クラスのプロテクトメンバーのみがアクセスできますが、派生クラスのオブジェクトや外部クラスではアクセスできません。
アクセス指定子のスコープ
| アクセス 指定子 | 自身のクラスからのアクセス | 派生クラスからのアクセス | 外部クラスのオブジェクトからのアクセス |
| パブリック | はい | はい | はい |
| プロテクト | はい | はい | いいえ |
| プライベート | はい | いいえ | いいえ |
継承を伴うアクセス指定子
| |
|
継承の種類
| |
|
| |
|
| | / 多重継承を示すプログラム /
#include
using namespace std;
class M
{
protected :
int m;
public :
void getm()
{
cout << “\nMの値を入力してください :”;
cin >> m;
}
};
class N
{
protected :
int n;
public :
void getn()
{
cout << “\nNの値を入力してください :”;
cin >> n;
}
};
class P : public N, public M
{
public :
void disp()
{
cout << “\n M = “ << m;
cout << “\n N = “ << n;
cout << “\n MN = “ << mn;
}
};
int main()
{
P p;
p.getm();
p.getn();
p.disp();
return 0;
} |
基底クラスが公開で継承される場合、パブリックメンバー、メンバ関数は派生クラスのメンバ関数やオブジェクトにもアクセス可能ですが、基底クラスがプライベートで継承される場合、基底クラスのパブリックメンバーは派生クラスのメンバ関数には継承されますが、オブジェクトには継承されません。
| | / 多層継承を示すプログラム /
class student
{
int rno;
public:
void getrno()
{
cout << “番号を入力してください :”;
cin >> rno;
}
void showrno()
{
cout << “学生番号:” << rno;
}
};
class test : public student
{
int m1,m2;
public :
void getmarks()
{
cout << “成績1を入力してください :” ; cin >> m1;
cout << “成績2を入力してください :” ; cin >> m2;
}
int retm1()
{
return m1;
}
int retm2()
{
return m2;
}
};
class result : public test
{
int tot;
public:
void get()
{
getrno();
getmarks();
}
void showresult();
void show()
{
showrno();
showresult();
}
};
void result::showresult()
{
int s1,s2;
s1=retm1();
s2=retm2();
tot=s1+s2;
cout << “\n成績 “ << s1 << “ “ << s2;
cout << “\n合計成績 “ << tot;
}
int main()
{
result a;
a.get();
a.show();
return 0;
} |
| | / ハイブリッド継承を示すプログラム /
#include
using namespace std;
class student
{
int rno;
public:
void getrno()
{
cout << “番号を入力してください :”;
cin >> rno;
}
void showrno()
{
cout << “\n学生番号 :” << rno;
}
};
class test : public student
{
protected :
int m1,m2;
public :
void getmarks()
{
cout << “成績1を入力してください :” ; cin >> m1;
cout << “成績2を入力してください :” ; cin >> m2;
}
void showmarks()
{
cout << “\n2科目の成績 ” << m1 << “ “ << m2;
}
};
class sports
{
protected :
int score;
public :
void getscore()
{
cout << “スコアを入力してください :”;
cin >> score;
}
};
class result : public test, public sports
{
public :
void getdata()
{
getrno();
getmarks();
getscore();
}
void putdata()
{
showrno();
showmarks();
cout << “\nスコア は “ << score;
cout << “\n 合計成績 “ << m1+m2;
}
};
int main()
{
result r;
r.getdata();
r.putdata();
return 0;
} |
上記プログラムの図解表現:
| | |
上記の図では、studentクラスがresultに2つの方法で継承されています。一つはtestを介して、もう一つはsportsを介して、共通の基底クラスstudentのメンバー、メンバ関数の2セットが派生クラスresultに継承されます。実行時に、システムはどの基底クラスのメンバ関数のセットを使用するか混乱します。
これは、共通の基底クラスを仮想基底クラスとして作成することで回避できます。
例:
| | class student { };
class test : virtual public student { };
class sports : virtual public student { };
class result : public test, sports { }; |
参考: Turbo C++におけるオブジェクト指向プログラミング: ロバート・ラフォール
新しい投稿を受信箱で受け取る
スパムはありません。いつでも購読を解除できます。