仮想関数とデストラクタ

仮想関数を持ったクラスを派生して、ベースクラスのポインタからアクセスしたいときは
ベースクラスのデストラクタを仮想関数にしないと、派生クラスのデストラクタが呼ばれない!

簡易的にクラスを書いたときに、
ベースクラス
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 <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();
};

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;
}