0

ご存知のように、クラスのメンバーにアクセスする方法はたくさんありますが、私の問題は今です。クラスconstructor/deconstructorがpublicの場合、「new」の使用が許可され、「extern」もプライベートの場合、「GetInstance」を「new」の使用を許可しないクラスのみにすることができます。これはクラスに適しています。それらにのみ1つのポインティングインスタンス(現在ログインしているユーザーをカウントするサーバーなど)が必要です。「new」は、多くのオブジェクトを指すクラス(たとえば、新しいオブジェクトを指すクラスなど)に適しています。新しいプレーヤーはintにログインし、それぞれに新しいポインタを作成します)、マップはそのオブジェクトの「新しい」へのポインタを格納します。問題は、「extern」がグローバルオブジェクトのプライベートコンストラクタからアクセスすることを許可されるべきではないということです。「新しい」以来 使用は許可されていませんか?以下の例を見てください。

#include <windows.h>
#include <cstdlib>
#include <iostream>
#include <map>

using namespace std;


//CMover.h-------------------------------------
#define MAX_MOVER_NAME 32

class CMover
{
private:
    BOOL m_bInitialized;
    BOOL m_bIsWalking;
    unsigned m_uMetersPercused;
    TCHAR m_szName[MAX_MOVER_NAME+1];

    //CMover( LPCTSTR szMoverName, BOOL bInitialized = TRUE, BOOL bWalking = TRUE, unsigned uMeters = 0 );

public:
        CMover() { };
    virtual ~CMover(){};
};
//---------------------------------------------



//CMover.cpp---------------
CMover g_Mover; //CMover was created in order to have many 'new' usage, so each 'new' object points to a new player
// Making a global object of it is a big failure
//---------------------------


//CServer.h---------------
class CConnectedUsers
{
private:
    CConnectedUsers() {}; //ok, new cannot access, this class should be used as 1 object only
    virtual ~CConnectedUsers() {}; //to count up connected users, 'new' should never be used
public:
    map<u_long,CMover*>m_UserMng;

    //I Could use GetInstance, that any pointers craeted (CConnectedUsers *pCUser = CConnectedUsers::GetInstance() ) would
    //point to it
    static CConnectedUsers* GetInstance( void )
    {
            static CConnectedUsers mObj;
            return &mObj;
    }
};
//------------------------

//CServer.cpp ------
//Or in this case i would like to make a global object, so on CWhatever.cpp that included CServer.h i could use
//(extern CConnectedUsers g_Users;) which is also 1 object-only so no GetInstance would be needed and I would use
//(g_Users.m_UserMng...) directly after external declared
//PROBLEM is, making constructor private regulates the class to be 1 object only, but it doesn't allow external usage
//why is that???
CConnectedUsers g_Users;
//-----------------

//Main.cpp ...etcc

int main( int argc, char *argv[] )
{
    CMover *pMover = new CMover;
    cout << pMover << endl << &pMover << endl; //points to a new object, pointer stored in a region

    CMover *pMov2 = new CMover;
    cout << pMov2 << endl << &pMov2 << endl << endl; //points to a new object, pointer stored in another region

    CConnectedUsers *pCUser = CConnectedUsers::GetInstance();
    CConnectedUsers *pCUser2 = CConnectedUsers::GetInstance();
    cout << pCUser << endl << &pCUser << endl; //points to CConnectedUsers, pointer stored in a region
        cout << pCUser2 << endl << &pCUser2 << endl; //points to same CConnectedUsers, pointer stored in another region

    //also another question is, do I need to check these pointers integrity by doing:
            if( pCUser )
            {
                //??
            }

    system("pause>nul");
    return EXIT_SUCCESS;
}
4

1 に答える 1

5

問題はありませんextern。での宣言externはオブジェクトを作成せず、コンストラクターへのアクセスを必要としません。

ただし、extern参照はどこかで定義されたオブジェクトを見つける必要があり、クラス メンバーではなく名前空間メンバーであるため、1 つの定義 (単なる宣言ではない) はコンストラクターにアクセスできません。

これは完全に予期されたものであり、一貫しています。名前空間スコープで評価される式はクラスの外にあるため、プライベート メンバーに関して特別な権限はありません。

代わりに、「ロック アンド キー」システムを使用して、パブリック コンストラクターを他のファイルから使用できないようにすることができます。例えば:

// header file
class Once
{
public:
    struct Forward;
    Once(Forward);
};

extern Once g_singleton;

// implementation file
#include "Once"
namespace { struct Local {}; }
struct Once::Forward : Local {};

Once g_singleton(Once::Forward());

Once::Forwardコンストラクターに値で渡す必要があるの定義が他のコンパイル単位にないため、他のコンパイル単位からクラスをインスタンス化することはできません。Once::Forwardまた、他のコンパイル単位で定義しようとすると、ODR 違反になります。

于 2012-06-18T22:11:58.710 に答える