10:友達なら当たり前

 さて、WinMain関数の中に先ほど作成したCGameObjectを作成し、Initialize()を実行させるわけなのですが、すべてのプログラムで1回きりしか使わない関数を
public
にするのはあまり意味はなく、派生クラスからもアクセスできてしまうのもなんだか不格好です。かといって
private
ではアクセスできない。そんなときに便利なのがフレンド関数です。
 フレンド関数はその名が示すように、ここで宣言された関数をクラスのお友達と見なし、クラス内の
private
な情報もフレンド関数から直接アクセスできるようになるのです。

 ためしにCGameObjectの宣言部分をこう変えてみましょう。
#pragma once

#include <tchar.h>
#include <windows.h>

#include <dxerr9.h>
#include <d3d9.h>
#include <d3dx9.h>

#define RELEASE(x) {if(x) x->Release();}

class CGameObject
{
private:
    static HWND hWnd;
    static HINSTANCE hInstance;
    
    BOOL Initialize(HWND hWnd, HINSTANCE hInstance);
    void Uninitialize();

    friend int APIENTRY _tWinMain(HINSTANCE, HINSTANCE, LPTSTR, int);

public:
    static const HWND GetHWnd(){ return hWnd; }
    static const HINSTANCE GetHInstance(){ return hInstance; }

protected:
    static LPDIRECT3D9 pD3D;
    static LPDIRECT3DDEVICE9 pD3Ddevice;
    static LPD3DXSPRITE pSprite;
};
 Initialize()とUninitialize()を
private
に、WinMain()宣言を
friend
としてクラス内に登録しました。この結果、
class CGameObjectChild : public CGameObject
{
    void FooUninitialize()
    {
        Uninitialize();
    }
};
 このように派生クラスからUninitialize()を呼び出しても、「privateなメンバにアクセスできません」と、コンパイルエラーになりますが、
int APIENTRY _tWinMain
(HINSTANCE hInstance, HINSTANCE hPrevInstance,
 LPTSTR lpszCmdLine, int nCmdShow)
{

    /* 省略 */

    HWND hWnd = CreateWindow(
        wc.lpszClassName,
        _T("クラスまみれのゲームプログラミング入門"),
        WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
        CW_USEDEFAULT, CW_USEDEFAULT, 640, 480,    
        NULL, NULL, hInstance, NULL );

    CGameObject game;
    game.Initialize(hWnd, hInstance);

    /* 省略 */

    game.Uninitialize();

    return 0;
}
 お友達の関数であるWinMain()内でInitialize()を呼び出しても、コンパイルエラーとならず、すんなりと実行ファイルが完成してしまいます。
 フレンドクラスなるものもC++には用意されており、こちらはお友達関係のクラスであれば、宣言しているクラスの
private
な情報であろうが、自由にいじくり回すことができ、このように使用できる場所を限定させることで、明確なプログラミングができるようになります。

 ただし、フレンド宣言を多用すると
private
の意味ないじゃん。てなことになりかねませんので、ご利用は計画的に。
// フレンドクラスのデモプログラム

#include <iostream>
using namespace std;

class Class2;    // あらかじめの宣言

class Class1
{
private:
    friend Class2;    // Class2をお友達にすることを宣言
    void Kansu()
    {
        cout << "privateな関数です" << endl;
    }
};

class Class2
{
public:
    void Kansu2()
    {
        Class1 c1;
        c1.Kansu();    // Class1のプライベートな関数にアクセス
    }
};

void main()
{
    Class2 c2;
    c2.Kansu2();
}