====== 仮想関数とデストラクタ ======
仮想関数を持ったクラスを派生して、ベースクラスのポインタからアクセスしたいときは\\
ベースクラスのデストラクタを仮想関数にしないと、派生クラスのデストラクタが呼ばれない!\\
簡易的にクラスを書いたときに、
ベースクラス
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;
}