Pregunta

En una gran cantidad de C ++ API de que make algo para usted, el puntero al objeto por lo general se requiere como un puntero ** que se construye (y la función (los vienen a la mente basado en COM) construirá y init para usted)

lo general, ver firmas como:

HRESULT createAnObject( int howbig, Object **objectYouWantMeToInitialize ) ;

-., Pero que rara vez se ve el nuevo objeto que se pasa como un valor de retorno

Además de las personas que quieren ver los códigos de error, ¿cuál es la razón de esto? ¿Es mejor utilizar el patrón ** en lugar de un puntero devuelto para las operaciones más simples, tales como:

wchar_t* getUnicode( const char* src ) ;

O sería mejor esto puede escribir como:

void getUnicode( const char* src, wchar_t** dst ) ;

Lo más importante que puedo pensar es recordar para liberarla, y la forma en **, por alguna razón, tiende a recordarme que tengo que cancelar la asignación él también.

¿Fue útil?

Solución

"Además de querer códigos de error"?

¿Qué le hace pensar que hay es un aparte. Los códigos de error son más o menos la única razón. La función de las necesidades de alguna manera para indicar el fallo. C no tiene excepciones, por lo que tiene que hacer que a través de ya sea un parámetro de puntero, o el valor de retorno y el valor de retorno es idiomático, y más fácil de comprobar cuando se llama a la función.

(Por cierto, no hay ninguna regla universal que los medios ** que tiene que liberar el objeto. Eso no es siempre el caso, y es probablemente una mala idea usar algo que arbitraria para recordarle que los objetos a limpiar.)

Otros consejos

Dos razones vienen a la mente.

En primer lugar están los códigos de error de hecho. Aparte de C ++, C no tiene excepciones, y COM es un C-API. También muchos proyectos de C ++ basado prefieren no utilizar excepciones, por diversas razones. Puede haber casos en los que un valor de retorno no puede detectar la avería, por ejemplo si su función devuelve un entero, puede que no haya valor entero, que puede representar un código de error. Si bien los errores con los punteros de señalización es fácil (NULL == Error), algunos diseñadores API prefieren los errores de señal de una manera coherente de todas las funciones.

En segundo lugar, las funciones sólo puede tener un valor de retorno, pero llamándolos puede crear varios objetos. Algunas funciones de la API de Win32 toman múltiples punteros a punteros que pueden rellenarse opcionalmente, si se llama a estas funciones con punteros no NULL. No puede devolver dos punteros, o más bien esto sería difícil de usar, si el valor de retorno es cierta estructura por el valor que contiene más de un puntero. En este caso también una API consistente es un objetivo razonable de lograr.

Los nuevos objetos en los argumentos de funciones aprobadas por ** es mejor. Esto me tome un consuelo para el uso futuro del cambio void a bool por ejemplo, para el éxito de retorno de una función o de otro tipo de información que proporciona trabajos de función.

respuesta en una sola línea:. Esto es mucho mejor para los que resulta códigos de error

  

Además de las personas que quieren ver los códigos de error, ¿cuál es la razón de esto?

Hay algunas razones para esto. Uno de ellos está escribiendo una interfaz que se puede utilizar en C (que se ve esto en la API de Windows y Windows COM).

compatibilidad con versiones anteriores es otra razón (es decir, la interfaz fue escrito así y romperlo ahora se rompería el código existente).

Me gustaría ir con la compatibilidad C durante un principio de diseño cuando se utiliza un código como éste. Si se va a escribir en C ++ que iba a escribir

retval Myfunction(Result *& output);

en lugar de

retval Myfunction(Result ** output);

o (aún mejor):

Result *Myfunction();

y tienen la función de producir una excepción en caso de error.

No estoy seguro estoy de acuerdo que es la mejor manera de hacerlo ... esto podría ser mejor:

Object * createAnObject(int howbig, HRESULT * optPlaceResultCodeHereIfNotNull = NULL);

De esta manera no hay perder el tiempo con doble vía indirecta (que puede ser un poco difícil para las personas que no están acostumbrados a ella), y las personas que no se preocupan por los códigos de resultado no tiene que preocuparse sobre el segundo argumento en absoluto ... que sólo puede comprobar para ver si el valor de retorno es NULL o no.

En realidad, ya que es C ++, podría facilitar las cosas aún, el uso de la sobrecarga de funciones:

Object * createAnObject(int howbig);
Object * createAnObject(int howbig, HRESULT & returnResultCode);

Cualquier llamada a un método en una llamada COM tiene que ser HRESULT. Los códigos de retorno consiguen aprovecharse todo el marco y pasando un doble puntero es una manera conocida para obtener el objeto creado.

No responder su pregunta, pero un comentario como su pregunta llevó a cabo algunos pensamientos que tengo acerca de COM / DCOM programación en C ++.

Todos estos "puntero" y "puntero a puntero", la gestión de la memoria y el recuento de referencias son las razones por las que se apartan de hacer la programación COM con C ++. Incluso con ATL en su lugar, me gusta por la sencilla razón de que no se ve muy natural. Una vez dicho esto, lo hice hacer un par de proyectos con ATL.

En aquel entonces la alternativa es el uso de VB. El código vB parece más natural para COM o programación DCOM.

Hoy en día, me gustaría utilizar C #.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top