====== 仮想関数とデストラクタ ====== 仮想関数を持ったクラスを派生して、ベースクラスのポインタからアクセスしたいときは\\ ベースクラスのデストラクタを仮想関数にしないと、派生クラスのデストラクタが呼ばれない!\\ 簡易的にクラスを書いたときに、 ベースクラス class cBase; cBase::cBase(); virtual void cBase::printMe(); ~cBase::cBase(); 継承クラス class cDerive:public cBase; int cDerive::m_value;//こっちで拡張されたメンバ変数 cDerive::cDerive() virtual void cDrive::printMe(); ~cDerive::cDerive(); があった時、 cBase *p = nullptr; p = new cDerive; とするとcBaseクラスのポインタに、派生クラスのオブジェクトの先頭アドレスを代入できる。 ただし、ベースクラスのポインタpからは、cDeriveのメンバのうちcBaseと共通のものにしかアクセスできない。 そこで、出てくる概念。 * 継承による関数の隠蔽 * 関数のオーバーライド * 仮想関数 * (純粋仮想関数、抽象クラス) ===== 今日やったサンプル ===== ==== cBase.h cBase.cpp ==== === cBase.h === #pragma once #include using namespace std; //using std::cout; //using std::endl; class cBase { //private://外部から隠蔽 protected://派生先だけに限定公開 int* kamoku;//科目数の配列へのポインタ public://丸出し大公開 //年齢 int m_age; //身長 double m_height; cBase() :m_age(0), m_height(0),kamoku(nullptr) { //cout << "cBase:コンストラクタ" << endl; printf("cBase:コンストラクタ\n"); } cBase(int _age, double _height, int _kamoku) :m_age(_age), m_height(_height) { kamoku = new int[_kamoku]; cout << "cBase:引数付コンストラクタ\n"; } virtual void printMe() { cout << m_age << "歳です\n"; } virtual ~cBase(); }; === cBase.cpp === #include "cBase.h" //デストラクタは引数なし、戻り値なしの //超特別な関数 cBase::~cBase() { //メモリリークをしないために //自分の動的に作ったものの後片付け //もの=動的なメンバ(配列、変数) if (kamoku != nullptr) { delete[] kamoku; cout << "配列kamokuを削除した\n"; } cout << "デストラクタ:cBase\n"; } ==== cDerive.h cDerive.cpp ==== === cDerive.h === #pragma once #include "cBase.h" class cDerive : public cBase { public: cDerive() // :cBase() //関数のインライン定義 { cout << "cDeriveが生成された!\n"; } cDerive(int _age, double _height, int _kamoku) :cBase(_age, _height, _kamoku) { //m_age = _age; //m_height = _height; //kamoku = new int[_kamoku]; cout << "cDerive(引数付き)が生成された!\n"; } void printMe() { cout << m_age << "歳" << m_height<< "cmです\n"; } ~cDerive();//cppの方に定義を書く //内容:cout << "デストラクタ:cDerive\n";を実行 }; === cDerive.cpp === #include "cDerive.h" cDerive::~cDerive() { //呼ばれたのがわかるだけの無意味デストラクタ cout << "デストラクタ:cDerive\n"; } ==== theMain.cpp ==== #include "cBase.h" #include "cDerive.h" int main() { //cBase yamada; //cBase *yamada = nullptr; //yamada = new cBase(18, 164.2); ////newはコンストラクタを呼んで出来た実体の ////アドレスを返す演算 //while (true) { // cBase yamada(19,168.5,2000); // //yamada = new cBase(19,169.5, 1000); // //delete[] yamada; // //delete[] yamada->kamoku; // //delete yamada; //} //delete yamada; ////newしたものは自分で消す。 //年齢,身長,科目数 //cDerive oDerive(19, 152, 10); //cDerive* p = nullptr; cBase* p = nullptr; p = new cDerive[2]{ {19, 152, 10}, { 20,180, 20 } }; //cout << p[0].m_age << "\n"; //cout << (p + 1)->m_age << "\n"; //cout << p[1].m_age << "\n";と同じ for(int i=0;i<2;i++) { (p + i)->printMe(); } delete[] p; return 0; }