Class 〜 End Class ステートメント

クラス名及びクラスを構成するメンバ変数、メンバ関数を定義します。


書式
Class ClassName [Inherits BaseClass] [Private] [statement] 'プライベート メンバ ステートメント Public [statement] 'パブリック メンバ ステートメント Protected [statement] 'プロテクティット メンバ ステートメント End Class
ClassName
クラス名を指定します。
Inherits BaseClass
BaseClassにベースクラスを指定するとインヘリタンス(継承)を行うことができます。InheritsはClass定義内の先頭に記述しなければなりません。また、継承を行わないときは省略することができます。
Private
ここから定義するメンバはプライベートアクセスであることを示します。アクセシビリティ(Private/Public/Protected)をなにも指定していないときはプライベートアクセスになります。プライベートアクセスは、クラス内のメンバ関数からのみ参照可能になり、継承先クラスのメンバ関数及び外部から参照することはできません。
Public
ここから定義するメンバはパブリックアクセスであることを示します。パブリックアクセスは、クラス内のメンバ関数及び外部からのアクセスが可能です。
Protected
ここから定義するメンバはプロテクティットアクセスであることを示します。クラス内のメンバ関数及び継承先のメンバ関数からのみ参照可能になり、外部から参照することはできません。
statement
メンバ変数及びメンバ関数の定義を行います。詳しくは下記の「メンバ定義ステートメント」をご覧ください。
※アクセシビリティ(Private/Public/Protected)の指定順序に決まりはありません。また、同じアクセシビリティは繰り返し指定することができます。



メンバ定義ステートメント(変数)の書式
Class CTest ... VarName [As VarType] VarName2 [As VarType2] ... End Class
VarName
メンバ変数の名前を指定します。メンバ変数名の後にカッコ[ ]で括った配列要素を指定することもできます。
VarType
メンバ変数のデータ型を指定します。
※メンバ変数は複数行にわたっていくつでも定義することができます。



メンバ定義ステートメント(関数)の書式
Class CTest ... '通常のメンバ関数の定義 Sub/Function FuncName ([arglist]) [As RetType] [statement] End Sub/Function '仮想関数の定義 Virtual Sub/Function FuncName ([arglist]) [As RetType] ... End Class
Sub/Function
Subを指定すると戻り値がないプロシージャが定義されます。Functionを指定すると戻り値がある関数が定義されます。
FuncName
関数の名前を指定します。関数名に "クラス名" または "~クラス名" を指定するとそれぞれコンストラクタ、デストラクタを指定することができます。詳しくは下記の「コンストラクタ、デストラクタについて」をご覧ください。
arglist
パラメータを指定します(詳細...)。
RetType
戻り値のデータ型を指定します。Function定義の場合のみ有効です。
statement
Sub 〜 End Sub、またはFunction 〜 End Functionの間にメンバ関数のプログラムコードを記述します。
Virtual
Virtualキーワードを指定すると仮想関数を定義することができます。仮想関数は外部のプログラムコードを呼び出すためのものであるため、この位置にそのコード内容を記述することはできません。詳しくは下記の「仮想関数について」をご覧ください。
※メンバ関数は複数行にわたっていくつでも定義することができます。



コンストラクタ、デストラクタについて

コンストラクタ、デストラクタはそれぞれオブジェクトの生成、消滅の際に呼び出される戻り値がない関数(Sub定義)です。関数名は "クラス名" 及び "~クラス名" が利用され、これらの名前を持つ関数は自動的にコンストラクタ、デストラクタと認識されます。

オブジェクトの生成時に呼び出されるコンストラクタではオブジェクトの初期化を行います。コンストラクタについてはパラメータを指定することができます。オブジェクトの消滅時に呼び出されるデストラクタではオブジェクトが利用したデータの破棄処理などを行います。デストラクタについてはパラメータを指定することはできません。

コンストラクタ及びデストラクタはクラス外から呼び出されるケースがほとんどのため、アクセシビリティをパブリックにセットしておく必要があります。

呼び出されるタイミング

コンストラクタ及びデストラクタは下記のように実態オブジェクトの定義を行うと、コンストラクタが自動的に呼び出されます。

Dim obj As CClass(param)

デストラクタは下記のようなオブジェクトが破棄されるタイミングで呼び出されます。
・グローバル領域で定義されたオブジェクトについてはプログラム終了時
・ローカル領域で定義されたオブジェクトについてはプロシージャ抜け出し時
New演算子で生成されたオブジェクトについては、Delete演算子を使用した時

コンストラクタ、デストラクタの省略

コンストラクタまたはデストラクタの定義を省略すると、下のような引数を持たない空のコンストラクタ、デストラクタが暗黙的に定義されます。

Sub ClassName()
    '空のコンストラクタ
End Sub

Sub ~ClassName()
    '空のデストラクタ
End Sub

クラスを継承したときのコンストラクタ、デストラクタの動き

クラスの継承が行ったとき、サブクラスのコンストラクタ、デストラクタ呼び出し時にはスーパークラス(継承元クラス)のコンストラクタの呼び出しを行います。

サブクラスのコンストラクタの定義を省略したとき、またはサブクラスのコンストラクタの先頭部分でスーパークラスのコンストラクタの呼び出しを行わなかったときは、スーパークラスのコンストラクタ呼び出しが引数無しで暗黙的に呼び出されます。呼び出し順序は下のようになります。

スーパークラスのコンストラクタの呼び出し

サブクラスのコンストラクタの呼び出し

サブクラスのデストラクタが呼び出された後に、スーパークラスのデストラクタが暗黙的に呼び出されます。

サブクラスのデストラクタの呼び出し

スーパークラスのデストラクタの呼び出し

メンバとして含まれる実体クラスのコンストラクタ、デストラクタの動き(コンポジション)

親クラスに属すメンバとして実体クラス(以後、メンバクラス)が定義されるとき、メンバクラスのコンストラクタ(引数が存在するものを除く)及びデストラクタは下記のような順序で自動的に呼び出されます。メンバクラスのコンストラクタが引数を持つとき、自動呼び出しは行われません。このような場合は任意に呼び出さなければならないので、注意が必要です。

メンバクラスのコンストラクタの呼び出し

親クラスのコンストラクタの呼び出し

親クラスのデストラクタが呼び出された後に、メンバクラスのデストラクタが暗黙的に呼び出されます。

親クラスのデストラクタの呼び出し

メンバクラスのデストラクタの呼び出し




仮想関数について

仮想関数は主にCOMインターフェイスを定義する際に活用します。具体的には下記のようにメンバ変数の先頭部分に関数ポインタの配列を示すポインタを保持します。

VTblPtr->Table[0]->Proc0
         Table[1]->Proc1
         Table[2]->Proc2
         Table[3]->Proc3
         Table[4]->Proc4

仮想関数の呼び出しは通常のメンバ関数と同様の手順で行うことができるため、特別が利用がない限りこれらの構造を意識する必要はありません。また、仮想関数を定義しただけでは関数ポインタには何のデータも格納されないため、インターフェイスの取得または任意の関数ポインタを格納する必要があります。




クラス定義及びオブジェクト生成の例

CHumanというクラスをベースに名前と誕生年、年齢を表示するプログラムです。

はじめにClass 〜 End ClassステートメントでCHumanクラスの定義を行います。名前、誕生年のデータはそれぞれpName、BirthYearというメンバ変数に格納することにします。pName、BirthYearの値設定及び参照はクラス内のメンバ関数を通して行うので、外部からアクセス不可能なプライベートで宣言します。続いて、メンバ関数を定義していきます。GetAge関数はBirthYearの値をもとに現在の年齢を計算する関数です。後に定義するメンバ関数ShowHumanDataから呼び出される以外は使われることがないので、プライベートで宣言しています。オブジェクトの生成、消滅時に呼び出されるコンストラクタ(CHuman関数)、デストラクタ(~CHuman関数)は共にパブリックなメンバ関数として定義します。コンストラクタでは初期データ(名前と誕生年)のセットを行います。デストラクタでは名前バッファで確保したメモリの解放を行います。ShowHumanData関数は名前、誕生年、年齢をメッセージボックスで表示する関数です。

クラスの定義が完了すれば、Dimステートメントを利用して実際にオブジェクトを生成できるようになります。ここではobj_dai、obj_yasuという2つのオブジェクトを生成しています。コンストラクタ、デストラクタがオブジェクトの生成時、関数抜け出し時に呼び出されるところに注目しておきましょう。オブジェクトが生成できたらそれぞれShowHumanData関数を呼び出してデータを表示して一連の流れは終了します。

Class CHuman pName As BytePtr '名前バッファへのポインタ BirthYear As Long '誕生年 '年齢を取得するための関数 Function GetAge() As Long Dim st As SYSTEMTIME GetLocalTime(st) GetAge=st.wYear-BirthYear End Function Public 'コンストラクタ Sub CHuman(buf As BytePtr, n As Long) 'メモリを確保し、名前をセット pName=malloc(lstrlen(buf)+1) lstrcpy(pName,buf) '誕生歳をセット BirthYear=n End Sub 'デストラクタ Sub ~CHuman() '名前で使用したメモリを解放 free(pName) End Sub 'データを表示するための関数 Sub ShowHumanData(hWnd As DWord) Dim buf[255] As Byte wsprintf(buf,Ex"名前:%s\r\n%d年生まれ\r\n今年で%d歳",pName,BirthYear,GetAge()) MessageBox(hWnd,buf,"Class Test",MB_OK) End Sub End Class Sub Main() 'オブジェクトを生成 Dim obj_dai As CHuman("Daisuke",1983) Dim obj_yasu As CHuman("Yasuharu",1984) Dim hDeskWnd As DWord hDeskWnd=GetDesktopWindow() 'オブジェクトのデータを表示する obj_dai.ShowHumanData(hDeskWnd) obj_yasu.ShowHumanData(hDeskWnd) 'デストラクタは関数終了時に自動的に呼び出される End Sub 'メイン関数の呼び出し Main()



New演算子Delete演算子メンバ関数のオーバーライド