2016-07-15 5 views
0

У меня есть синглтон с несколькими статическими методами и методами экземпляра. Я хотел бы экспортировать его в DLL, чтобы я мог использовать его в другом месте. Однако это вызвало предупреждение компилятора, потому что я не экспортировал частных членов данных класса.Использование PIMPL с singleletons и auto_ptr

Итак, в своих исследованиях я натолкнулся на идиому PIMPL и увидел, что ее можно использовать для выполнения того, что я хочу делать. Пожалуйста, давайте воздержимся от того, пока аргумент «Синглтоны являются злыми/анти-шаблонами». В моем случае это имеет смысл, потому что мне нужен класс менеджера для всех моих под-объектов. Для краткости я собираюсь сократить некоторые другие методы в классе, но я оставлю достаточно для общей идеи.

Идея пустого HIDDevice деструктора в файле HIDDeviceImpl СРР происходит от this article Али Çehreli

HIDDevice.hpp

class HIDDeviceImpl; // Forward Declaration 

class HIDDevice 
{ 
public: 

    static HIDDevice* getDevice(unsigned short vendorID, unsigned short productID); 

    int writeData(const unsigned char *data, int length); 


    int readData(unsigned char *data, int length); 

    ~HIDDevice(); // Note public destructor declared in HIDDevice.hpp 

private: 

    std::unique_ptr<HIDDeviceImpl> m_pImpl; // pointer to the implemetation 
}; 

HIDDevice.cpp

#include "HIDDeviceImpl.hpp" 
#include "HIDDevice.hpp" 

HIDDevice* HIDDevice::getDevice(unsigned short vendorID, unsigned short productID) 
{ 
    return HIDDeviceImpl::getDevice(vendorID, productID); 
} 

int HIDDevice::writeData(const unsigned char *data, int length) 
{ 
    return m_pImpl->writeData(data, length); 
} 


int HIDDevice::readData(unsigned char *data, int length) 
{ 
    return m_pImpl->readData(data, length); 
} 

HIDDeviceImpl.hpp

#include "HIDDevice.hpp" 

class HIDDeviceImpl : public HIDDevice 
{ 
public: 

    static HIDDeviceImpl* getDevice(unsigned short vendorID, unsigned short productID); 

    int writeData(const unsigned char *data, int length); 

    int readData(unsigned char *data, int length); 

private: 
    // some private static and private member functions and data 
    // private constructor and destructor 
}; 

HIDDeviceImpl.hpp

#include "HIDDeviceImpl.hpp" 

/** Non-member Static Data Definitions **/ 
/** internal map used to store all HIDDevice objects */ 
static std::map<std::string, HIDDeviceImpl*> m_hidDevices; 

HIDDeviceImpl* HIDDeviceImpl::getDevice(unsigned short vendorID, unsigned short productID) 
{ 
    //implementation 
} 

int HIDDeviceImpl::writeData(const unsigned char *data, int length) 
{ 
    //implementation 
} 

int HIDDeviceImpl::readData(unsigned char *data, int length) 
{ 
    //implementation 
} 

HIDDeviceImpl::HIDDeviceImpl(unsigned short vendorID, unsigned short productID, std::string serialNumber) 
{ 
    // implementation 
} 

HIDDeviceImpl::~HIDDeviceImpl() 
{ 
    // implementation 
} 

// Note the HIDDevice destructor is declared in the HIDDeviceImpl file. 
HIDDevice::~HIDDevice() 
{ 
    // intentionally left blank 
} 

Теперь, ошибка это порождает следующий:

error C2248: 'HIDDeviceImpl::~HIDDeviceImpl' : cannot access private member declared in class 'HIDDeviceImpl' 

Это вытекающий из auto_ptr в HIDDevice .hpp

+1

В то время как 'std :: auto_ptr' был хорошей первой попыткой принести интеллектуальные указатели в мир C++, это некорректно, а' std :: auto_ptr' устарели с C++ 11 и будут удалены в C++ 17. Либо используйте ручное управление указателями, либо используйте новый ['std :: unique_ptr'] (http://en.cppreference.com/w/cpp/memory/unique_ptr). –

+1

'unique_ptr' и связанные с ним ptrs были созданы для замены сломанного' auto_ptr'. Обратите внимание, что статья с 2002 года. – SurvivalMachine

+0

Класс pImpl в идиоме Pimpl не является результатом «открытого класса». Фактически, публичный класс не должен появляться нигде в pImpl, потому что в противном случае у вас есть круговая ссылка – KABoissonneault

ответ

1

Почему бы просто не сделать то, что вам сообщает сообщение об ошибке, и сделать публикацию деструктора общедоступной? Таким образом, внутренняя часть std::unique_ptr имеет к ней доступ.

+0

Потому что я не хочу, чтобы объект был уничтожен преждевременно ошибкой программиста. – audiFanatic

+0

@audiFanatic Он не будет уничтожен на ранней стадии ошибки программиста, потому что 'm_pImpl' доступен только из HIDDevice (потому что он закрыт) – KABoissonneault

+0

@KABoissonneault Правда, я думаю, что сначала попытаюсь реализовать фактический PIMPL (согласно ваши другие комментарии), и тогда я отдам это. – audiFanatic