Version 17.02
派生クラスでのメンバの追加
「前回は継承を使用してみました」
『継承を使うと、基本クラスのメンバ変数やメンバ関数をそのまま持った
クラスを作ることができる、っていうことなんだよね』
「そういうこと。クラスの後ろに【 : public クラス名】と付けることで、
このクラスの機能を引き継ぐことができます」
// CData クラスの派生クラス。
class CDerivedData : public CData
{
};
「で、さらにこのクラスにメンバ変数やメンバ関数を加えることができるん
です」
『あ、それできるんだ』
「それがメインかな。メンバの追加は、単純に派生クラスでメンバを作れば
OK。たとえばこんな感じに」
// Data.h
// CData クラス。
class CData
{
public:
// データ格納用メンバ変数。
int m_iData;
// 出力用メンバ関数。
void Output();
};
// CData クラスの派生クラス。
class CDerivedData : public CData
{
public:
// データ格納用メンバ変数2。
int m_iData2;
// 出力用メンバ関数2。
void Output2();
};
// Data.cpp
#include <Windows.h>
#include <stdio.h>
#include "Data.h"
// 出力用メンバ関数。
void CData::Output()
{
// m_iData を出力します。
char pch[256];
sprintf( pch, "%d\n", m_iData );
OutputDebugString( pch );
// 100
}
// 出力用メンバ関数2。
void CDerivedData::Output2()
{
// m_iData2 を出力します。
char pch[256];
sprintf( pch, "%d\n", m_iData2 );
OutputDebugString( pch );
// 100
}
「この例では CDerivedData クラスに m_iData2 メンバ変数と
Output2 メンバ関数を追加しています」
『本当に、普通にメンバ変数とメンバ関数作るだけで追加されるんだね』
「そういうこと。使用例はこんな感じ」
// Main.cpp
#include <Windows.h>
#include <stdio.h>
#include "Data.h"
int WINAPI WinMain
( HINSTANCE p_hInstance
, HINSTANCE p_hPrevInstance
, LPSTR p_pchCmdLine
, int p_iCmdShow
)
{
// CDerivedData クラスを使用します。
CDerivedData cDerivedData;
cDerivedData.m_iData = 100;
cDerivedData.Output();
// 100
// CDerivedData クラスで追加したメンバを使用します。
cDerivedData.m_iData2 = 200;
cDerivedData.Output2();
// 200
return 0;
}
「このように CDerivedData クラスは、基本クラスのメンバも、
派生クラスのメンバも使うことができる、というわけです」
『こうして機能の追加ができるってわけね。これってつまり、
CDerivedData クラスに CData クラスのメンバ変数とメンバ関数が追加され
たって考えればいいんだよね』
「ううん、正確にはちょっと違うかな。正確には、 CDerivedData クラスの
中に CData クラスが入っている感じ。図にするとこんな感じかな」
┌───────────┐
│ CDerivedData │
│ ┌────────┐ │
│ │CData │ │
│ │ │ │
│ │m_iData │ │
│ │Output() │ │
│ └────────┘ │
│ m_iData2 │
│ Output2() │
└───────────┘
『中に入ってる……』
「そう、つまり CData クラスと CDerivedData クラスは独立してるってこ
と。これが重要になるのは、基本クラスのメンバが private の場合」
『 private って、外からアクセスできなくなるってあれだよね』
「 Version 16.04 ( No.331 ) で説明したね。で、実は private にする
と、派生クラスからも使用できなくなります」
『マジですか』
// Data.h
// CData クラス。
class CData
{
private:
// データ格納用メンバ変数。
int m_iData;
};
// CData クラスの派生クラス。
class CDerivedData : public CData
{
public:
// 基本クラスの m_iData に値をセットします。
void SetData( int p_i );
};
// Data.cpp
#include <Windows.h>
#include <stdio.h>
#include "Data.h"
// 基本クラスの m_iData に値をセットします。
void CDerivedData::SetData( int p_i )
{
m_iData = p_i;
// コンパイルエラー:
// data.cpp(11) : error C2248: 'm_iData' :
// private メンバ (クラス 'CData' で宣言されている)に
// アクセスできません。
}
「この例では、 CData クラスの m_iData メンバ変数を private にしてい
ます」
// CData クラス。
class CData
{
private:
// データ格納用メンバ変数。
int m_iData;
};
「そのため、派生クラスのメンバ関数から使用しようとすると
コンパイルエラーになります」
// 基本クラスの m_iData に値をセットします。
void CDerivedData::SetData( int p_i )
{
m_iData = p_i;
// コンパイルエラー:
// data.cpp(11) : error C2248: 'm_iData' :
// private メンバ (クラス 'CData' で宣言されている)に
// アクセスできません。
}
『ホントだ……ってことは、図にするとこんな感じ?』
┌──────────────┐
│ CDerivedData │
│ ┌────────┐ │
│ │CData │ │
│ │ │ │
│ │m_iData ×←←←│←← │
│ └────────┘ ↑ │
│ SetData() →→→→→→ │
└──────────────┘
「そう、 m_iData メンバ変数は private だから、〈外のクラス〉の
CDerivedData クラスからはアクセスできないわけです」
/*
Preview Next Story!
*/
『基本クラスと派生クラスは独立してる……』
「そう、だから private だとアクセスできないんです」
『 public だとアクセスできる、でも外からもだよね』
「実は、継承関係専用のアクセス指定があるんです」
『マジですか』
「というわけで次回」
< Version 17.03 protected メンバ >
『につづく!』
「これまで謎に包まれていた protected の意味が、今!」
『……今答言わなかった?』