既存のクラスを基にして新しいクラスを作ることを,クラスの継承 (inheritance) と呼ぶ。
継承の話をするために、(良い設計ではないが)円を表すクラスと、円柱を表すクラスを考える。
円を表すクラス
//実はインデントは2日4つの半角スペースが標準派がおおい。 //今後参考にしていくgoogleのコード規約でもスペース class cBase { int x, y; //メンバ変数 public: //↓ここからのメンバはパブリック(公開) cBase() //コンストラクタは2つオーバーロードしてある :x(0), y(0), r(0.0), area(0) { cout << "生誕" << endl; } //メンバイニシャライザによる初期化 cBase(int _x, int _y, double _r) :x(_x), y(_y), r(_r),area(0) {//areaは0を入れておいて後で計算 cout << "生誕" << endl; SetArea();//areaを計算 } ~cBase() { cout << "消滅" << endl; } //デストラクタ double r;//メンバ変数 void PrintMember(); //メンバ関数(公開)宣言のみ double GetArea() { return(area); } private://↓ここからのメンバは再びプライベート(非公開) double area;//メンバ変数 void SetArea(); //面積を計算してareaにセットする関数 宣言のみ };
#include "cBase.h" void cBase::PrintMember()//メンバ関数(公開) { cout << "中心: (" << x << "," << y << ")" << endl; cout << "半径:" << r << endl; cout << "面積:" << area << endl; } void cBase::SetArea() //面積を計算してareaにセットする { const double pi = 3.14159265359; area = pi * r * r; } // cBase:: の中ではpublic,private区別
#include <iostream> #include "cBase.h" #include "cCylinder.h" using std::cout; using std::cin; using std::endl; int main() { //特にコンストラクタを指定しないと引数なしコンストラクタが呼ばれる cBase inVar; //クラスからできた変数=インスタンス=C++でのオブジェクト cBase inVar2(10, 5, 3.0); inVar.PrintMember(); inVar2.PrintMember(); return(0); }
クラスを設計するには、そのクラスをモデル化(抽象化)することが大事です。
簡単には、
そのオブジェクトを表すのに必要なパラメータ ⇒ メンバ変数
そのオブジェクトのふるまいを表すもの ⇒ メンバ関数
になります。
cBaseクラスの場合
次は、先ほどのcBaseクラスを継承して、cCylinderクラスを作ってみます。
説明のために無理やり作ったクラスなので設計としてはよくありません。(むしろダメ)
余裕のある人はこの設計のどこがダメなのか考えてみよう!
hint: 前に言った、基底クラスと派生クラスの関係は、どんなかんけいになってるのがよかったっけ?
考え方としては、形状(円)を拡張して(高さと体積の属性をプラス)して円柱クラスを作る。
です。
#include "cBase.h" class cCylinder : public cBase { double height; double volume; void SetVolume(); public: cCylinder() :cBase(),height(0),volume(0) { cout << "円柱爆誕" << endl; } cCylinder(int _x, int _y, double _r, double _h) :cBase(_x, _y, _r), height(_h), volume(0) //Volumeは0にして後で計算 { cout << "円柱爆誕" << endl; SetVolume(); //Volumeを計算してセット! } //void PrintMember(); //メンバ関数(公開)宣言のみ };
#include "cCylinder.h" void cCylinder::SetVolume() { //volume = area * height; //これはできない! areaはベースのプライベートメンバだから volume = GetArea() * height; }
int main() { cCylinder inCy(10, 5, 3.0, 5.0); //中心(10,5) 半径 3.0 高さ5.0の円柱 inCy.PrintMember(); return(0); }
ってな感じになります。
* 実行結果
PrintMember関数が、cBaseクラスに実装されているので、新しく追加したメンバを表示できていませんね(上面と底面の円の属性を表示しちゃってる)。
次はこれをどうしたらcCylinderクラスのメンバ詳細を表示できるのかってのを考えてみます。