【问题标题】:extern must have access to class constructor?extern 必须有权访问类构造函数?
【发布时间】:2012-06-20 22:49:53
【问题描述】:

众所周知,有很多方法可以访问班级成员,我现在的问题是。如果类构造函数/解构函数是公共的,则允许“新”使用以及“外部”,如果它是私有的,我可以只创建不允许“新”使用的“GetInstance”类,这对类有好处应该只有 1 个指向它们的实例(例如计算当前登录用户的服务器),并且“新”适用于指向许多对象的类(例如指向新对象的类,例如新玩家登录 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;
}

【问题讨论】:

    标签: c++ class pointers constructor extern


    【解决方案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。

    【讨论】:

    • 哦,是的,你说得非常对,我的想法是错误的,我非常专注于在我的其他文件上使用它,它甚至没有出现我试图创建一个没有权限的对象.关于如何以这种方式使用“外部”的任何想法?
    • 哦,我明白了,使用命名空间不是我的习惯,我会期待的。谢谢^^
    • 嘿,如果我在使用'getinstance'方法时必须检查指针完整性,请回答。
    • @ViniciusHorta:变量的地址总是非空的。只有从工厂函数(例如malloc)返回或显式设置为 NULL 的指针有时可以为 NULL。
    • 如果Once::Forward 被多次定义,编译器是否应该警告你?
    猜你喜欢
    • 2015-07-04
    • 1970-01-01
    • 2014-07-02
    • 1970-01-01
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-24
    相关资源
    最近更新 更多