2009-02-24 18 views
5

Tengo un buffer char (es decir, un byte) que estoy enviando a través de la red. En algún momento en el futuro podría querer cambiar el buffer a un tipo diferente como unsigned char o short. He estado pensando en hacer algo como esto:¿Uso válido de typedef?

typedef char bufferElementType; 

Y cada vez que hago cualquier cosa con un elemento amortiguador lo declaro como bufferElementType en lugar de char. De esa forma podría cambiar a otro tipo cambiando este typedef (por supuesto, no sería tan simple, pero al menos sería fácil identificar los lugares que necesitan ser modificados ... habrá un bufferElementType cerca) .

¿Es este un uso válido/bueno de typedef? ¿No vale la pena el problema? ¿Me va a dar dolor de cabeza en algún momento en el futuro? ¿Va a hacer que los programadores de mantenimiento me odien?

He leído a través de When Should I Use Typedef In C++, pero nadie realmente cubrió esto.

+0

¿Utiliza matrices de este tipo para sus almacenamientos intermedios? ¿O quiere decir que el búfer tiene una longitud de 1 byte, y es posible que desee convertirlo en 2 bytes o 4 bytes en el futuro? –

+0

En ese caso, no hay mucha ventaja al usar "typedef char bufferElementType;". Si utiliza el mismo tamaño de matriz en todas partes, puede ser útil escribir def de todo el tipo de matriz: "typedef char [1024] bufferElementType;" - que te permite cambiar el tamaño del búfer en todas partes de una vez. –

+0

Sin embargo, si sus búferes son realmente para contener "caracteres de texto" y está considerando cambiar de una codificación de caracteres exactamente 1 byte (por ejemplo ANSI) a una codificación de caracteres exactamente 2 byte o exactamente 4 bytes, su original typedef es el camino a seguir. –

Respuesta

11

Es un uso excelente (y normal). Sin embargo, debe tener cuidado de que, por ejemplo, el tipo que selecciona cumple los mismos criterios de firma/no firma, o que responden de manera similar a los operadores. Entonces sería más fácil cambiar el tipo después.

Otra opción es usar plantillas para evitar fijar el tipo hasta el momento de compilar. Una clase que se define como:

template <typename CharType> 
class Whatever 
{ 
    CharType aChar; 
    ... 
}; 

es capaz de trabajar con cualquier tipo char selecciona, al tiempo que responde a todos los operadores de la misma manera.

+0

No entiendo qué ventajas tiene typedef en este caso. El único propósito de la variable de almacenamiento intermedio es proporcionar un número determinado de bytes de almacenamiento, y char es siempre el tamaño de la unidad de almacenamiento direccionable más pequeña. ¿Puede darnos un escenario donde sería útil cambiar el tipo typedefed? –

+0

char a wchar, por ejemplo; char para XMLChar (libxml2), etc. Reconozco que el caso de un único char no es el más interesante, pero dar nombres que describen semánticamente a los tipos también es una buena práctica, aparte de las otras razones que di. –

+0

Sí, ese es un caso de uso. La pregunta del consultante me dio la sensación de que estaba interesado en un búfer de * bytes *, pero si se supone que debe contener caracteres de texto en alguna codificación (de tamaño fijo pero posiblemente multibyte), entonces es apropiado considerar diferentes tipos de elementos de búfer. –

1

Sí, esto es el uso perfecto para typedef, al menos en C.

para C++ se puede argumentar que las plantillas son una mejor idea (como Diego Sevilla ha sugerido) pero tienen sus inconvenientes. (Trabajo adicional si todo lo que utiliza el tipo de datos no está incluido en algunas clases, tiempos de compilación más lentos y una estructura de archivos fuente más compleja, etc.)

También tiene sentido combinar los dos enfoques, es decir, dar un nombre typedef a un parámetro de plantilla.

Tenga en cuenta que, como está enviando datos a través de una red, char y otros tipos enteros pueden no ser intercambiables (por ejemplo, debido a endian-ness). En ese caso, usar una clase de plantilla con funciones especializadas podría tener más sentido. (Enviar < carbón > envía el byte, enviar <corta> lo convierte a la red de orden de bytes primero)

Sin embargo, otra solución sería la creación de una clase "BufferElementType" con métodos auxiliares (convertToNetworkOrderBytes()) pero apuesto eso sería un exagerado para ti.

2

Otra ventaja de typedefs es que, si se usan con prudencia, pueden aumentar la legibilidad. Como un ejemplo realmente tonto, un Meter y un Degree pueden ser dobles, pero te gustaría diferenciarlos. El uso de un typedef es una rápida solución & fácil de make errors more visible.

Nota: una solución más robusta para el ejemplo anterior habría sido crear diferentes tipos para un metro y un grado. Por lo tanto, el compilador puede hacer cumplir las cosas por sí mismo. Esto requiere un poco de trabajo, que no siempre da sus frutos, sin embargo.El uso de typedefs es una manera fácil de & para hacer que sea visible, como se describe en el artículo vinculado anteriormente.

+0

typedefs definitivamente puede aumentar la legibilidad, sin embargo, no pueden hacer que los errores sean más visibles ya que son solo alias que el compilador traduce inmediatamente a su tipo subyacente. Entonces, si el Meter y el Degree son typedefed al doble, el código "Meter x; Degree y; x = y;" compila sin errores. –

+0

Nunca dije lo contrario. Es mucho mejor si el compilador puede aplicarlo por sí mismo. Pero eso requiere más código. Una solución rápida y fácil es hacer que sea visible para HUMANS. Consulte el artículo vinculado para obtener más información. –

+0

Bastante justo. Puede evitar la asignación directa accidental entre tipos usando "class Meter {double _x; public: Meter (double x): _x (x) {}; operator double &() {return _x;}};" y lo mismo para Degree; pero esto todavía permite, p. "Medidor x; Grado y; x = y + 5;". Esto también se puede evitar, pero es más difícil. –