仮想関数を持ったクラスを派生して、ベースクラスのポインタからアクセスしたいときは
ベースクラスのデストラクタを仮想関数にしないと、派生クラスのデストラクタが呼ばれない!
簡易的にクラスを書いたときに、 ベースクラス 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と共通のものにしかアクセスできない。
そこで、出てくる概念。
#pragma once #include <iostream> 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(); };
#include "cBase.h" //デストラクタは引数なし、戻り値なしの //超特別な関数 cBase::~cBase() { //メモリリークをしないために //自分の動的に作ったものの後片付け //もの=動的なメンバ(配列、変数) if (kamoku != nullptr) { delete[] kamoku; cout << "配列kamokuを削除した\n"; } cout << "デストラクタ:cBase\n"; }
#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";を実行 };
#include "cDerive.h" cDerive::~cDerive() { //呼ばれたのがわかるだけの無意味デストラクタ cout << "デストラクタ:cDerive\n"; }
#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; }