У меня есть синглтон с рядом статических методов и методов экземпляра. Я хотел бы экспортировать его в DLL, чтобы я мог использовать его в другом месте. Однако это вызвало предупреждение компилятора, потому что я не экспортировал закрытые данные-члены класса.
Итак, в своем исследовании я наткнулся на идиому PIMPL и увидел, что ее можно использовать для того, чтобы делать именно то, что я хочу делать. Пожалуйста, давайте воздержимся от аргумента «Синглтоны — это зло/анти-паттерны». В моем случае это имеет смысл, потому что мне нужен класс менеджера для всех моих подобъектов. Для краткости я собираюсь сократить некоторые другие методы в классе, но оставлю достаточно для общей идеи.
Идея пустого деструктора HIDDevice
в файле HIDDeviceImpl
CPP взята из этой статьи Али Чехрели.
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.
std::auto_ptr
была хорошей первой попыткой внедрить интеллектуальные указатели в мир C++, она оказалась ошибочной, аstd::auto_ptr
устарела, начиная с C++11, и будет удалена в C++17. Либо используйте ручное управление указателями, либо используйте новыйstd::unique_ptr
. - person Some programmer dude   schedule 15.07.2016unique_ptr
и связанные с ним указатели были созданы для замены сломанногоauto_ptr
. Обратите внимание, статья 2002 года. - person SurvivalMachine   schedule 15.07.2016HIDDevice
также должен быть синглтоном? - person audiFanatic   schedule 15.07.2016HIDDevice
илиHIDDeviceIMpl
? - person audiFanatic   schedule 15.07.2016writeData
иreadData
вHIDDevice
и заставьте реализацию этих функций вызывать эти функции в синглтоне внутри. Гораздо меньше проблем для пользователя - person KABoissonneault   schedule 15.07.2016