Классы-оболочки Win API для дескрипторов

Написать класс-оболочку для дескриптора, который передается только по значению, относительно легко. Я пытаюсь определить, как лучше всего инкапсулировать дескрипторы, которые необходимо передать по адресу.

Например, написать оболочку для чего-то вроде SC_HANDLE, которая передается по значению в QueryServiceConfig(), не так сложно. Можно либо реализовать функцию-член, например .GetHandle(), либо реализовать operator().

Проблема (по крайней мере, для меня) заключается в функциях API, таких как RegOpenKeyEx(), которым нужен адрес HKEY.

Я читал, что оператор перегрузки & вообще плохая идея. Каков рекомендуемый способ сохранения инкапсуляции (или максимально возможной ее части) и особенно сбора ресурсов при разрешении доступа к функциям API?


person links77    schedule 20.04.2011    source источник
comment
В таких случаях я предпочитаю модели Attach() и Detach(). Вы можете реализовать оператор &, но я считаю, что это очень уродливо. На самом деле нет правильного ответа; это скорее личные предпочтения.   -  person Luke    schedule 21.04.2011


Ответы (1)


Вы всегда можете добавить еще один уровень косвенности, чтобы избежать ужасной перегрузки operator& и уродливых Attach или Detach и вернуть оттуда предварительно упакованный экземпляр.

Если вы можете использовать C++0x в VS2010 или gcc или иметь другие способы доступа к std::unique_ptr<>, вы можете сделать это (проверка ошибок для краткости опущена):

struct hkey_deleter
{
    void operator()(HKEY hkey)
    {
        ::RegCloseKey(hkey);
    }
};

typedef std::unique_ptr<HKEY__, hkey_deleter> regkey;

regkey MyRegOpenKeyEx(HKEY hKey, LPCTSTR lpSubKey, DWORD ulOptions, REGSAM samDesired)
{
    HKEY hOpenedKey = NULL;
    ::RegOpenKeyEx(hKey, lpSubKey, ulOptions, samDesired, &hOpenedKey);

    return regkey(hOpenedKey);
}

void SomewhereElse()
{
    ...
    regkey r = MyRegOpenKeyEx(HKEY_CLASSES_ROOT, nullptr, 0, KEY_READ);
    ...
}

hkey_deleter позаботится о том, чтобы раздел реестра был закрыт при выходе из области видимости или вызове regkey::reset().

person Johann Gerell    schedule 20.04.2011