Вопрос

Во многих странах 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 #.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top