** idiom в C ++ для объекта
-
25-09-2019 - |
Вопрос
Во многих странах C ++ API (на основании COM-COM-COM-COMPS), что сделать что-то для вас, указатель на предмет, который построен, обычно требуется в качестве **
Указатель (и функция построит и инициаторует его)
Вы обычно видите подписи, такие как:
HRESULT createAnObject( int howbig, Object **objectYouWantMeToInitialize ) ;
- Но вы редко смотрите новый объект, переданный как возвращаемое значение.
Помимо людей, желающих увидеть коды ошибок, в чем причина этого? Лучше использовать **
Узор, а не возвращенный указатель для более простых операций, таких как:
wchar_t* getUnicode( const char* src ) ;
Или это лучше будет написано как:
void getUnicode( const char* src, wchar_t** dst ) ;
Самое главное, что я могу думать, - это помнить, чтобы освободить его, а **
Способ по какой-то причине, стремятся напомнить мне, что я также должен освободить его.
Решение
«Помимо желания кодов ошибок»?
Что заставляет тебя там думать является кроме того. Коды ошибок в значительной степени единственной причиной. Функция нуждается в некотором смысле, чтобы указать сбой. C Нет исключения, поэтому он должен сделать это через параметр указателя, либо возвращаемое значение, а возвращаемое значение идиоматично и легче проверить при вызове функции.
(Кстати, нет универсального правила, которое **
означает, что вы должны освободить объект. Это не всегда так, и это, вероятно, плохая идея использовать что-то, что произвольно напоминает вам о том, какие объекты убирать.)
Другие советы
Две причины приходят на мой взгляд.
Сначала есть коды ошибок на самом деле. Кроме C ++, C не имеет исключения, а COM - это C-API. Также многие проекты на основе C ++ предпочитают не использовать исключения по разным причинам. Могут быть случаи, где возвращаемое значение не может сигнализировать о ошибках, например, если ваша функция возвращает целое число, не может быть целочисленного значения, которое может представлять код ошибки. При ошибках сигнализации с указателями легко (NULL == ERROR), некоторые дизайнеры API предпочитают сигнализируют ошибки последовательным способом по всем функциям.
Во-вторых, функции могут иметь только одно возвращаемое значение, но вызывая их, может создать несколько объектов. Некоторые функции API Win32 принимают несколько указателей к указателям, которые можно заполнить необязательно, если вы вызываете эти функции с ненулевыми указателями. Вы не можете вернуть два указателя, точнее, это было бы неловко использовать, если возвращаемое значение является некотором структурой по значению, содержащему более одного указателя. Здесь также последовательная API - это разумная цель для достижения.
Новые объекты в функциональных аргументах прошли **
лучше. Это возьмет у меня комфорт для будущего использования изменений void
к bool
Например, чтобы вернуть успех функции или другую информацию о предоставлении функции работы.
Ответ в одной строке: Это намного лучше для полученных кодов ошибок.
Помимо людей, желающих увидеть коды ошибок, в чем причина этого?
Есть некоторые причины для этого. Один из них пишет интерфейс, который используется в C (вы видите это в Winapi и Windows COM).
Обратная совместимость - это еще одна причина (т.е. интерфейс был написан так, как и сломал его теперь сломал существующий код).
Я бы пошел с совместимостью C для принципа дизайна при использовании подобного кода. Если бы вы написали в C ++, вы бы написали
retval Myfunction(Result *& output);
вместо
retval Myfunction(Result ** output);
или (даже лучше):
Result *Myfunction();
И иметь функцию бросить исключение на ошибку.
Я не уверен, что я согласен, что это лучший способ сделать это ... Это может быть лучше:
Object * createAnObject(int howbig, HRESULT * optPlaceResultCodeHereIfNotNull = NULL);
Таким образом, нет возиться с двумя подрастями (что может быть немного сложно для людей, которые не привыкли к этому), а люди, которым не заботится о кодах результатов, не нужно беспокоиться о втором Аргумент вообще ... они могут просто проверить, будет ли значение возвращаемой нолью или нет.
На самом деле, поскольку это C ++, вы можете сделать все еще проще, используя перегрузку функций:
Object * createAnObject(int howbig);
Object * createAnObject(int howbig, HRESULT & returnResultCode);
Любой вызов метода в COM Call должен быть Hresult. Коды возврата получают используемые по всему каркану и передают двойной указатель - это известный способ получить созданный объект.
Не отвечая на ваш вопрос, но комментарий, поскольку ваш вопрос выяснил некоторые мысли, у меня есть программирование COM / DMOC, используя C ++.
Все эти «указатели» и «указатель на указатель», Memory Management и ссылочные считаются причины, по которым я уклоняюсь от программирования COM с C ++. Даже с ATL на месте мне не нравится по той простой причине, что она не выглядит достаточно естественно. Сказав это, я сделал несколько проектов, использующих ATL.
Вернуться тогда альтернативу используют VB. Код VB выглядит более естественно для программирования COM или DCOM.
Сегодня я бы использовал C #.