Eu vi código C ++ como o seguinte com muitos typedef
s.
Quais são os benefícios de usar muitos typedef
s como este, em vez de usar primitivas C ++? Existe outra abordagem que também possa alcançar esses benefícios?
No final, todos os dados são armazenados na memória ou transmitidos pelo fio como bits e bytes, isso 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 tentar garantir que o mesmo tipo seja sempre usado para uma coisa específica, a fim de evitar estouros, mas geralmente vejo código em que "int" foi usado praticamente em todo lugar. O typedef
ing geralmente leva a um código que se parece um pouco com isso:
DoSomething(EscalationLevel escalationLevel) {
...
}
O que me faz pensar em qual token está realmente descrevendo o parâmetro: o tipo ou o nome do parâmetro?
c++
data-structures
Marca
fonte
fonte
Minute
para uma função que possui um argumento declarado como tipoSecond
.Respostas:
O nome de um parâmetro deve descrever o que isso significa - no seu caso, o nível de escalação. O tipo é como o valor é representado - adicionar typedefs, como no seu exemplo, ofusca essa parte da assinatura da função, então eu não o recomendaria.
Typedefs são úteis para modelos, ou se você deseja alterar o tipo usado para determinados parâmetros, por exemplo, ao migrar de uma plataforma de 32 bits para uma de 64 bits.
fonte
int32_t
é que você precisa se certificar de que eles estão corretos ao compilar em plataformas diferentes. Se você espera que o intervaloIdentity
mude em algum momento, acho que preferiria fazer as alterações diretamente em todo o código afetado. Mas não tenho certeza, porque precisaria saber mais sobre seu design específico. Você pode fazer disso uma pergunta separada.No começo, pensei "Por que não", mas me ocorreu que, se você se esforçar tanto para separar os tipos assim, use melhor o idioma. Em vez de usar aliases, defina realmente os tipos:
Não há diferença de desempenho entre:
e:
e você também tem as vantagens de adicionar validação de parâmetro e segurança de tipo. Por exemplo, considere o código que lida com dinheiro usando tipos primitivos:
Além dos problemas de arredondamento, ele também permite qualquer tipo que possa ser convertido em um flutuador:
Nesse caso, não é grande coisa, mas as conversões implícitas podem ser uma fonte de erros difíceis de identificar. Usar a
typedef
não ajuda aqui, pois eles são apenas um alias de tipo.Usar um novo tipo inteiramente significa que não há conversões implícitas, a menos que você codifique um operador de conversão, o que é uma má ideia especificamente porque permite conversões implícitas. Você também pode encapsular dados adicionais:
Nada mais se encaixará nessa função, a menos que escrevamos código para que isso aconteça. Conversões acidentais são impossíveis. Também podemos escrever tipos mais complexos, conforme necessário, sem muito aborrecimento.
fonte
BOOST_STRONG_TYPEDEF
realmente;)O uso de typedefs para tipos primitivos assim se parece mais com o código de estilo C.
No C ++, você receberá erros interessantes assim que tentar sobrecarregar funções para, digamos,
EventLevel
eHour
. Isso torna os nomes de tipo extra bastante inúteis.fonte
Nós (em nossa empresa) fazemos muito em C ++. Ajuda a entender e manter o código. O que é bom ao mover pessoas entre equipes ou refatorar. Exemplo:
Acreditamos que é uma boa prática criar typedef para o nome da dimensão a partir do tipo de representação. Esse novo nome representa uma função geral em um software. O nome de um parâmetro é uma função local . Como em
User sender, User receiver
. Em alguns lugares, pode ser redundantevoid register(User user)
, mas não considero um problema.Posteriormente, pode-se ter a idéia de que
float
não é o melhor para representar preços por causa das regras especiais de arredondamento da reserva; portanto, é possível baixar ou implementar um tipoBCDFloat
(decimal codificado binário) e alterar o typedef. Não há pesquisa e substituir o trabalho defloat
paraBCDFloat
que se endureça pelo fato de que existem possivelmente muitos mais carros alegóricos em seu código.Não é uma bala de prata e tem suas próprias advertências, mas achamos que é muito melhor usá-la do que não.
fonte
BOOST_STRONG_TYPEDEF(float, Price)
dizer: mas eu não iria tão longe em um projeto comum. Ou talvez eu faria. Eu tenho que dormir nisso. :-)typedef
basicamente permite que você dê um alias para umtype
.Oferece a flexibilidade de evitar a digitação longa
type names
repetida e repetida e tornar suatype
leitura mais fácil, em que o nome alternativo indica a intenção ou o objetivo datype
.É mais uma questão de escolha se você deseja ter nomes mais legíveis
typedef
no seu projeto.Normalmente, evito usar
typedef
tipos primitivos, a menos que sejam muito longos para serem digitados. Eu mantenho meus nomes de parâmetro mais indicativos.fonte
Eu nunca faria algo assim. Certificar-se de que todos tenham o mesmo tamanho é uma coisa - mas você só precisa se referir a eles como tipos integrais.
fonte
Usar typedefs como este é bom, desde que quem os use não precise saber nada sobre sua representação subjacente . Por exemplo, se você deseja passar um
PacketLength
objeto para umprintf
ou outroscanf
, precisará conhecer seu tipo real para poder escolher o especificador de conversão correto. Em casos como esse, o typedef apenas adiciona um nível de ofuscação sem comprar nada em troca; você também pode ter definido o objeto comoint32_t
.Se você precisar aplicar semântica específica para cada tipo (como intervalos ou valores permitidos), é melhor criar um tipo de dados e funções abstratos para operar com esse tipo, em vez de apenas criar um typedef.
fonte