segunda-feira, 3 de agosto de 2009
Prefira consts à #defines
É uma prática comum entre programadores c/c++ - principalmente programadores provenientes do c puro - o uso de macros de pré-processamento ou seja, os #defines.
Este post vem, justamente lhe dizer para parar de fazer isso. Diremos o porquê não usar essa macro nos seus programas futuros e também quando você deve usar - se for preciso.
Em resumo esse post quer dizer: prefira o compilador ao pré-processador.
Considere: #define F 6.666
Então todas as evidencias de F serão retiradas e substituidas por 6.666, antes antes do código ser efetivamente compilado pelo compilador, pelo pré-processador. Portanto 'F' não entrará na tabela de símbolos.
Isso pode ser confuso num momento posterior. Afinal, o compilador pode apontar erros na parte do código em que anteriormente encontráva-se o símbolo 'F'. Contudo, o erro apontado será para o '6.666' pois é ele que está no código que o compilador está tentando compilar.
Se você tem essa macro ('F') num arquivo separado, onde, talvez, você e/ou o usuário futuro nem ao menos tenham acesso, será muito difícil encontrar o erro apontado pelo compilador.
Prefira: const double F = 6.666;
Isso deve corrigir o problema acima descrito. E ganhamos ainda um benefício extra: O código será menor.
Por quê?
Porque com o #define temos possivelmente multiplas cópias de 6.666 por todo o código, enquanto com a constante teremos certamente apenas uma cópia.
Constantes dentro de classes.
Se a constante estiver dentro de um scopo de uma classe toda, então você deve declará-la como statica, para evitar multiplas cópias desnecessárias.
Em algum momento dentro de classes, na declaração de arrays com tamanho constante, talvez precise de um hack. Isso porque o compilador pode 'sismar' em querer saber, logo na classe, o tamanho do array, para tanto podemos usar o enum hack. Simples, declare um enum na classe que inicia no tamanho que você deseja e use-o como constante.
Não use #define para função.
Considere: #define CALL_WITH_MAX(a, b) f((a) > (b) ? (a) : (b))
Por que não usar?
imagine que, com a = 5 e b = 0, você chame:
CALL_WITH_MAX(++a, b); // a é incrementado duas vezes
CALL_WITH_MAX(++a, b+10); // a é incrementado apenas uma vez
Podemos juntar a eficiência das macros mais o comportamento prático e a segurança de tipagem de uma função regular usando Templates para uma função inline.
template
inline void callWithMax(const T& a, const T& b)
{
f(a > b ? a : b);
}
(Note a constante para refencia. Abordamos isso e outras coisas semelhantes em um outro poste).
Com consts, enums e inlines você reduz a necessidade do preprocessador (especialmente #defines), mas não elimina. #include, por exemplo é essencial, e #ifndef e #ifndef que continuam a ser importante no controle da compilação. Também para códigos legados que usavam #defines e etc.
Lembre-se:
* prefira objetos consts ou enums à #defines.
* para funções do tipo macro, prefira função inline à #defines.
Referencia:
Effective C++ Third Edition 55 Specific Ways to Improve Your Programs and Designs By Scott Meyers
Este post vem, justamente lhe dizer para parar de fazer isso. Diremos o porquê não usar essa macro nos seus programas futuros e também quando você deve usar - se for preciso.
Em resumo esse post quer dizer: prefira o compilador ao pré-processador.
Considere: #define F 6.666
Então todas as evidencias de F serão retiradas e substituidas por 6.666, antes antes do código ser efetivamente compilado pelo compilador, pelo pré-processador. Portanto 'F' não entrará na tabela de símbolos.
Isso pode ser confuso num momento posterior. Afinal, o compilador pode apontar erros na parte do código em que anteriormente encontráva-se o símbolo 'F'. Contudo, o erro apontado será para o '6.666' pois é ele que está no código que o compilador está tentando compilar.
Se você tem essa macro ('F') num arquivo separado, onde, talvez, você e/ou o usuário futuro nem ao menos tenham acesso, será muito difícil encontrar o erro apontado pelo compilador.
Prefira: const double F = 6.666;
Isso deve corrigir o problema acima descrito. E ganhamos ainda um benefício extra: O código será menor.
Por quê?
Porque com o #define temos possivelmente multiplas cópias de 6.666 por todo o código, enquanto com a constante teremos certamente apenas uma cópia.
Constantes dentro de classes.
Se a constante estiver dentro de um scopo de uma classe toda, então você deve declará-la como statica, para evitar multiplas cópias desnecessárias.
Em algum momento dentro de classes, na declaração de arrays com tamanho constante, talvez precise de um hack. Isso porque o compilador pode 'sismar' em querer saber, logo na classe, o tamanho do array, para tanto podemos usar o enum hack. Simples, declare um enum na classe que inicia no tamanho que você deseja e use-o como constante.
Não use #define para função.
Considere: #define CALL_WITH_MAX(a, b) f((a) > (b) ? (a) : (b))
Por que não usar?
imagine que, com a = 5 e b = 0, você chame:
CALL_WITH_MAX(++a, b); // a é incrementado duas vezes
CALL_WITH_MAX(++a, b+10); // a é incrementado apenas uma vez
Podemos juntar a eficiência das macros mais o comportamento prático e a segurança de tipagem de uma função regular usando Templates para uma função inline.
template
inline void callWithMax(const T& a, const T& b)
{
f(a > b ? a : b);
}
(Note a constante para refencia. Abordamos isso e outras coisas semelhantes em um outro poste).
Com consts, enums e inlines você reduz a necessidade do preprocessador (especialmente #defines), mas não elimina. #include, por exemplo é essencial, e #ifndef e #ifndef que continuam a ser importante no controle da compilação. Também para códigos legados que usavam #defines e etc.
Lembre-se:
* prefira objetos consts ou enums à #defines.
* para funções do tipo macro, prefira função inline à #defines.
Referencia:
Effective C++ Third Edition 55 Specific Ways to Improve Your Programs and Designs By Scott Meyers
Hellow World
"Hellow World."
Olá, Bem Vindo, aqui será abordado assuntos como o desenvolvimento de jogos e o c++ para usuários avançados - ou seja, você já deve ter conhecimento da linguagem e de orientação a objetos.
O desenvolvimento de jogos aqui abordado trará tópicos como a computação gráfica, entrando em sub-tópicos como OpenGL e SDL - meus preferidos. Assim como o design do código dos jogos, design paterns, e o desenvolvimento geral de games.
O código dos jogos desenvolvidos por mim e comentados aqui serão postados, e estarão sob licensa GPL.
Nos tópicos do c++ avançado terá boas práticas de programação, como manter o código seguro e estável, estudo de algumas APIs, técnicas novas e/ou clássicas de programação para deixar o programa eficiente legível e seguro e estável. Também tópicos de lógica de programação e matemática. Trarei assuntos relacionados a programação orientada a objetos, design paterns, e outros abordados nos livros relacionados.
Nos própios tópicos também terá as referencias bibliográficas que consultei para escrever o post.
Olá, Bem Vindo, aqui será abordado assuntos como o desenvolvimento de jogos e o c++ para usuários avançados - ou seja, você já deve ter conhecimento da linguagem e de orientação a objetos.
O desenvolvimento de jogos aqui abordado trará tópicos como a computação gráfica, entrando em sub-tópicos como OpenGL e SDL - meus preferidos. Assim como o design do código dos jogos, design paterns, e o desenvolvimento geral de games.
O código dos jogos desenvolvidos por mim e comentados aqui serão postados, e estarão sob licensa GPL.
Nos tópicos do c++ avançado terá boas práticas de programação, como manter o código seguro e estável, estudo de algumas APIs, técnicas novas e/ou clássicas de programação para deixar o programa eficiente legível e seguro e estável. Também tópicos de lógica de programação e matemática. Trarei assuntos relacionados a programação orientada a objetos, design paterns, e outros abordados nos livros relacionados.
Nos própios tópicos também terá as referencias bibliográficas que consultei para escrever o post.
Assinar:
Postagens (Atom)