¿Qué tan lejos va con la tipificación de tipos primitivos como int

13

He visto código C ++ como el siguiente con muchos typedef s.

¿Cuáles son los beneficios de usar muchos typedef s como este en lugar de usar primitivas de C ++? ¿Hay otro enfoque que también podría lograr esos beneficios?

Al final, todos los datos se almacenan en la memoria o se transmiten por el cable como bits y bytes, ¿realmente importa?

types.h:

typedef int16_t Version;
typedef int32_t PacketLength;
typedef int32_t Identity;
typedef int32_t CabinetNumber;
typedef int64_t Time64;
typedef int64_t RFID;
typedef int64_t NetworkAddress;
typedef int64_t PathfinderAddress;
typedef int16_t PathfinderPan;
typedef int16_t PathfinderChannel;
typedef int64_t HandsetSerialNumber;
typedef int16_t PinNumber;
typedef int16_t LoggingInterval;
typedef int16_t DelayMinutes;
typedef int16_t ReminderDelayMinutes;
typedef int16_t EscalationDelayMinutes;
typedef float CalibrationOffset;
typedef float AnalogValue;
typedef int8_t PathfinderEtrx;
typedef int8_t DampingFactor;
typedef int8_t RankNumber;
typedef int8_t SlavePort;
typedef int8_t EventLevel;
typedef int8_t Percent;
typedef int8_t SensorNumber;
typedef int8_t RoleCode;
typedef int8_t Hour;
typedef int8_t Minute;
typedef int8_t Second;
typedef int8_t Day;
typedef int8_t Month;
typedef int16_t Year;
typedef int8_t EscalationLevel;

Parece lógico intentar y asegurarse de que siempre se use el mismo tipo para una cosa en particular para evitar desbordamientos, pero a menudo veo el código donde "int" se ha usado casi en todas partes. Sin embargo, el typedef ing a menudo conduce a un código que se parece a esto:

DoSomething(EscalationLevel escalationLevel) {
    ...
}

Lo que me hace preguntarme qué token está describiendo realmente el parámetro: ¿el tipo de parámetro o el nombre del parámetro?

    
pregunta Mark 20.06.2011 - 12:00

7 respuestas

13

El nombre de un parámetro debe describir lo que significa, en su caso, el nivel de escalación. El tipo es cómo se representa el valor: agregar typedefs como en su ejemplo confunde esta parte de la función de firma, por lo que no lo recomendaría.

Los typedefs son útiles para las plantillas, o si desea cambiar el tipo utilizado para ciertos parámetros, por ejemplo al migrar de una plataforma de 32 bits a una de 64 bits.

    
respondido por el Björn Pollex 20.06.2011 - 12:03
17

Al principio pensé "¿Por qué no?", pero luego se me ocurrió que si vas a hacer todo lo posible para separar los tipos así, haz un mejor uso del lenguaje. En lugar de utilizar alias, defina tipos:

class AnalogueValue
{
public:
    // constructors, setters, getters, etc..
private:
    float m_value;
};

No hay diferencia de rendimiento entre:

typedef float AnalogueValue;
AnalogValue a = 3.0f;
CallSomeFunction (a);

y:

AnalogValue a (3.0f); // class version
CallSomeFunction (a);

y también tiene las ventajas de agregar validación de parámetros y seguridad de tipos. Por ejemplo, considere el código que trata con el dinero usando tipos primitivos:

float amount = 10.00;
CallSomeFunction(amount);

Aparte de los problemas de redondeo, también permite que cualquier tipo se pueda convertir en un flotador:

int amount = 10;
CallSomeFunction(amount);

En este caso, no es un gran problema, pero las conversiones implícitas pueden ser una fuente de errores que es difícil de precisar. El uso de typedef no ayuda aquí, ya que no son más que un alias de tipo.

El uso de un nuevo tipo por completo significa que no hay conversiones implícitas a menos que usted codifique un operador de casting, lo cual es una mala idea específicamente porque permite conversiones implícitas. También puede encapsular datos adicionales:

class Money {
  Decimal amount;
  Currency currency;
};

Money m(Decimal("10.00"), Currency.USD);
CallSomeFunction(m);

Nada más encajará en esa función a menos que escribamos código para que esto suceda. Las conversiones accidentales son imposibles. También podemos escribir tipos más complejos según sea necesario sin mucha molestia.

    
respondido por el Skizz 20.06.2011 - 12:14
3

El uso de typedefs para tipos primitivos como el que se parece más a un código de estilo C.

En C ++ obtendrá errores interesantes tan pronto como intente sobrecargar funciones para, por ejemplo, EventLevel y Hour . Eso hace que los nombres de tipo extra sean bastante inútiles.

    
respondido por el Bo Persson 20.06.2011 - 12:48
1

typedef básicamente te permite dar un alias para un type .
Te da la flexibilidad de evitar escribir el largo type names una y otra vez y hacer que tu type sea más fácil de leer, en donde el nombre de alias indica la intención o el propósito del type .

Es más una cuestión de elección si desea tener más nombres legibles a través de typedef en su proyecto.
Por lo general, evito usar typedef en tipos primitivos, a menos que sean inusualmente largos para escribirlos. Mantengo los nombres de mis parámetros más indicativos.

    
respondido por el Alok Save 20.06.2011 - 12:03
1

Nosotros (en nuestra compañía) lo hacemos mucho en C ++. Ayuda a entender y mantener el código. Lo que es bueno al mover personas entre equipos o hacer refactorización. Ejemplo:

typedef float Price;
typedef int64_t JavaTimestmap;

void f(JavaTimestamp begin, JavaTimestamp end, Price income);

Creemos que es una buena práctica crear typedef al nombre de la dimensión a partir del tipo de representación. Este nuevo nombre representa un rol general en un software. El nombre de un parámetro es un rol local . Al igual que en User sender, User receiver . En algunos lugares puede ser redundante, como void register(User user) , pero no lo considero un problema.

Más adelante, uno puede tener la idea de que float no es el mejor para representar los precios debido a las reglas especiales de redondeo de la reserva, por lo que uno descarga o implementa un tipo BCDFloat (decimal codificado en binario) y cambia el typedef. No hay trabajo de búsqueda y reemplazo desde float a BCDFloat , lo cual se vería reforzado por el hecho de que posiblemente haya muchos más flotantes en su código.

No es una bala de plata y tiene sus propias advertencias, pero creemos que es mucho mejor usarla que no.

    
respondido por el Notinlist 13.10.2015 - 16:47
0

Nunca haría algo como esto. Asegurarse de que todos tengan el mismo tamaño es una cosa, pero solo necesita referirse a ellos como tipos integrales, entonces.

    
respondido por el DeadMG 20.06.2011 - 12:03
0

El uso de typedefs como este está bien siempre que quienquiera que termine usándolos no necesite saber nada sobre su representación subyacente . Por ejemplo, si desea pasar un objeto PacketLength a printf o scanf , deberá conocer su tipo real para poder elegir el especificador de conversión correcto. En casos así, el typedef solo agrega un nivel de ofuscación sin comprar nada a cambio; también podría haber definido el objeto como int32_t .

Si necesita imponer una semántica específica para cada tipo (como rangos o valores permitidos), es mejor que cree un tipo de datos abstractos y funciones para operar en ese tipo, en lugar de solo crear un typedef.

    
respondido por el John Bode 20.06.2011 - 20:41

Lea otras preguntas en las etiquetas