Как лучше всего инкапсулировать оконные ручки? - PullRequest
4 голосов
/ 02 ноября 2010

Я разрабатываю систему, состоящую из множества независимых подсистем. Двумя из таких подсистем являются Window и подсистема GraphicsAdapter.

Для GraphicsAdapter требуется низкоуровневый дескриптор окна (дескриптор окна HWND или X11, в зависимости от операционной системы), а подсистема Window - это способ абстрагирования этих специфичных для ОС API.

Если бы подсистема Window предоставляла доступ к низкоуровневым дескрипторам API, был бы большой потенциал для нарушения инкапсуляции.

Что, если он позволял окнам переходить в полноэкранный режим и назад, но должен был запускать события, предупреждающие систему об этих изменениях, а низкоуровневый маркер использовался для переключения в полноэкранный режим без его ведома?

Как я могу гарантировать, что дескриптор будет безопасно переноситься из подсистемы Window в GraphicsAdapter без злоупотребления и при этом быть достаточно гибким, чтобы впоследствии можно было добавлять другие подсистемы, такие как GraphicsAdapter, при этом поддерживая безопасность типов?

Есть ли способ инкапсулировать дескрипторы таким образом, чтобы Direct3D и OpenGL могли получить достаточно доступа из дескриптора для работы должным образом?

- редактировать

Помимо безопасного переноса дескрипторов из одной подсистемы в другую, зная, например, что подсистемы могут быть написаны другой командой кодировщиков, есть ли способ напомнить им о способе использования дескриптора?

Комментарии - очевидный выбор, но что-то навязанное компилятором - это то, что я действительно ищу ...

Ответы [ 3 ]

6 голосов
/ 02 ноября 2010

Оба HWND и дескрипторы окна X11 являются типами указателей.Вы можете использовать это в ваших интересах.Сделайте что-то вроде этого:

struct WindowHandleImpl;
typedef WindowHandleImpl *WindowHandle;

C ++ позволяет отлично работать с указателями на неполные типы - просто нигде не определяйте содержимое WindowHandleImpl, а WindowHandle - совершенно непрозрачный тип, который можетпередаваться приложением без раскрытия каких-либо подробностей реализации.

Поскольку HWND, X11 Window и WindowHandle - это все типы указателей, вы можете свободно перемещаться между ними без потерь.Поэтому, когда вам нужно вернуть дескриптор обернутого окна в приложение, вы делаете static_cast<WindowHandle>(some_hwnd), и тот же трюк работает в обратном порядке, когда вам нужно конвертировать указанный WindowHandle в фактический тип платформы.

Если вам когда-либо понадобится портировать на платформу, которая не использует тип указателя для обозначения дескрипторов окна, вы можете заключить это в структуру / класс и вернуть указатель на это.

2 голосов
/ 02 ноября 2010

Выставлять операции над дескриптором через виртуальные функции:

class GenericHandle
{
    public:
        virtual void some_operation() = 0;
};

// Windows API
class WindowsHandle : public GenericHandle
{
    public:
        virtual void some_operation()
        {
            WndOperation (handle_);
        }
    private:
        HANDLE* handle_;
};

// Some X system API
class XHandle : public GenericHandle
{
    public:
        virtual void some_operation()
        {
           XOperation (handle_);
        }
    private:
        XVOID* handle_;
};

Возможный способ настройки GraphicsAdapter:

GraphicsAdapter* ga = new GraphicsAdapter(GenericHandleFactory::get_handle(SYSTEM_ID));
0 голосов
/ 05 ноября 2010

Документируйте, как вы ожидаете, что он будет использоваться.

Доверяйте другим программистам в вашей команде.

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

...