オブジェクト指向のツボ 〜Vol8. Thisオブジェクト〜

例えば、クラスCTestが定義されたとすると、そのクラス内では自動的に

CTest This

というオブジェクトが定義されます(生成ではなく、定義です)。これをThisオブジェクトといい、クラス内で自身を参照する場合なんかに利用します。

とはいっても、通常はメンバ関数が始まれば、自身のメンバ変数は直接名指しで指名していたので、わざわざThisを使う必要性なんてあるのでしょうか??

考えてみてください。自身のメンバは直接名指しで参照できますが、オブジェクト自身を参照することはできませんよね。このように、Thisオブジェクトは、オブジェクト自身を外部に引き渡す際などに利用するものだと考えればよいでしょう。

オブジェクトを自爆させる

具体例を挙げてみましょう。オブジェクトが自身を破壊する動きを、Thisオブジェクトを使って再現してみます。このようなテクニックは、シューティングゲームでミサイルなどを表現する際によく使われます(ミサイルは敵機にあたった後、敵機もろとも自爆するってことですね)。

まずは、SelfKillerという関数を作って、それをオブジェクトが自爆するまで、繰り返し呼びつづけます。

メッセージボックスを使って、オブジェクトが自爆を容認した時点で、Delete VarPtr(This) を実行してオブジェクト自身を破棄します。ここで注意したいところが、Deleteに渡すのはオブジェクトポインタであるという部分です。Thisオブジェクトのポインタを渡してやらなければならないので、"Delete This" ではなく、"Delete VarPtr(This)" と指定しているところに注意してください。

#N88BASIC

Class CTest
Public

    'コンストラクタ
    Sub CTest()
        Print "オブジェクトが生成されました。"
    End Sub

    'デストラクタ
    Sub ~CTest()
        Print "オブジェクトが破棄されました。"
    End Sub

    '自爆処理を行う関数
    Function SelfKiller() As Long
        Dim lResult As Long

        lResult=MessageBox(_PromptSys_hWnd,"このオブジェクトを破棄しますか?","タイトル",MB_YESNO)

        If lResult=IDYES Then
            Print "このオブジェクトはまもなく自爆します";
            Print "・";
            Sleep(700)
            Print "・";
            Sleep(700)
            Print "・"
            Sleep(700)

            'オブジェクトを破棄
            Delete VarPtr(This)

            SelfKiller=1
        Else
            Print "このオブジェクトは自爆をためらっているようです";
            Print "・";
            Sleep(700)
            Print "・";
            Sleep(700)
            Print "・"
            Sleep(700)

            SelfKiller=0
        End If
    End Function
End Class

Dim lResult=0 As Long

'オブジェクトを生成
Dim pObj As *CTest
pObj = New CTest

'オブジェクトの自爆を催促
While(lResult=0)
    lResult = pObj->SelfKiller()
Wend

↑実行結果

その他のThisオブジェクトの利用方法

先ほどは、オブジェクトの自爆をサンプルに挙げましたが、Thisオブジェクトを使ったテクニックは外部に自身のオブジェクトを渡す場合にも利用します。

下のサンプルでは、CMyWindowというウィンドウの座標を管理するクラスを定義し、更にその座標をスクリーンの中央に持ってくるための関数SetCenterを定義しています。

SetCenter関数のパラメータを見るとお分かりかと思いますが、そこにはCMyWindowオブジェクトがあります。ということは、SetCenter関数をCMyWindowクラス内から呼び出す場合は、そのオブジェクト自身(This)を渡してやらなければならないんですね。

幅、高さを取得するためのGetWidth、GetHeightにもオブジェクト自身(This)を渡しています。こちらにも注目してみましょう。

#N88BASIC

Class CMyWindow
Public
    left As Long
    top As Long
    right As Long
    bottom As Long

    'コンストラクタ
    Sub CMyWindow()
        left=0
        top=0
        right=100
        bottom=50

        'ウィンドウ座標を中央にもってくる
        SetCenter(This)

        Print "オブジェクトが生成されました。"
    End Sub

    'デストラクタ
    Sub ~CMyWindow()
        Print "オブジェクトが破棄されました。"
    End Sub

    Sub ShowRectangle()
        Dim width As Long
        Dim height As Long

        width=GetWidth(this)
        height=GetHeight(this)

        Print
        Print "left=";left
        Print "top=";top
        Print "right=";right
        Print "bottom=";bottom
        Print "幅  ";width;"ピクセル"
        Print "高さ";height;"ピクセル"
        Print
    End Sub
End Class



Sub SetCenter(ByRef WndObj As CMyWindow)
    '-------------------------------------------
    ' ウィンドウ座標を中央にあわせるための関数
    '-------------------------------------------
    Dim ScreenX As Long
    Dim ScreenY As Long
    Dim width As Long
    Dim height As Long

    'スクリーンの大きさを取得
    ScreenX = GetSystemMetrics(SM_CXSCREEN)
    ScreenY = GetSystemMetrics(SM_CYSCREEN)

    With WndObj
        width = .right - .left
        height = .bottom - .top

        .left = ( ScreenX - ( .right - .left ) ) / 2
        .top = ( ScreenY - ( .bottom - .top ) ) / 2

        .right = .left + width
        .bottom = .top + height
    End With
End Sub

Function GetWidth(ByRef WndObj As CMyWindow)
    '-------------------------
    ' 幅を取得するための関数
    '-------------------------

    GetWidth=WndObj.right - WndObj.left
End Function

Function GetHeight(ByRef WndObj As CMyWindow)
    '-------------------------
    ' 高さを取得するための関数
    '-------------------------

    GetHeight=WndObj.bottom - WndObj.top
End Function



'オブジェクトを生成
Dim pMyWnd As *CMyWindow
pMyWnd = New CMyWindow

'座標を表示
pMyWnd->ShowRectangle()

Delete pMyWnd

↑実行結果



講座インデックスへ戻る ©2005 Discoversoft