extern должен иметь доступ к конструктору классов?
Есть много способов получить доступ к ученикам, как вы все знаете, моя проблема сейчас. если конструктор / деконструктор класса, если public, использование 'new' разрешено, а также 'extern', если это private, я могу сделать класс GetInstance только тем, который не позволит использовать 'new', что хорошо для класса он должен иметь только один указывающий экземпляр (например, сервер, который считает текущих зарегистрированных пользователей), а 'new' подходит для classe, указывающего на многие объекты (например, класс, указывающий на новые объекты, например, новый игрок зарегистрировал 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;
}
1 ответ
Проблема не в extern
, Декларация с extern
не создает объект и не нуждается в доступе к конструктору.
Тем не менее, extern
ссылка должна найти объект, определенный где-то, и одно определение (не просто объявление) не имеет доступа к конструктору, так как это член пространства имен, а не член класса.
Это вполне ожидаемо и последовательно. Выражения, оцениваемые в области имен, находятся вне класса и поэтому не имеют специальных привилегий в отношении закрытых членов.
Вместо этого вы можете использовать систему с замком и ключом, чтобы сделать публичный конструктор непригодным для использования из любого другого файла. Например:
// 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.