Une discussion a récemment pris fin en mocking des mauvaises habitudes des programmeurs qui ont été trop exposés à une langue quand ils commencent à programmer dans une autre langue. Le meilleur exemple serait un programmeur Pascal commençant à #define begin {
et #define end }
en commençant à écrire C.
L’objective est d’essayer d’attraper les mauvaises habitudes des programmeurs C lorsqu’ils commencent à utiliser le C ++.
Parlez du gros ne que vous avez rencontré. Une suggestion par réponse, s’il vous plaît, d’essayer de réaliser une sorte de meilleur de.
Pour ceux qui sont intéressés par de bonnes habitudes, jetez un œil à la réponse acceptée à cette question .
Utilisation de pointeurs et de ressources bruts au lieu d’objects RAII.
Déclarer toutes les variables en haut d’une fonction au lieu d’être aussi proches que possible de l’endroit où elles sont utilisées.
Ne pas utiliser la STL, en particulier std :: ssortingng,
et / ou
en utilisant std :: ssortingngs et en revenant à l’ancienne fonction c ssortingng dans les virages serrés.
utiliser des pointeurs au lieu de références
Ajout de using
dans les fichiers d’en-tête afin qu’ils puissent éviter des noms tels que std::ssortingng
dans les déclarations de type.
Développeurs très expérimentés ne comprenant pas le casting ni même la programmation orientée object:
J’ai commencé à participer à un projet et l’un des frameworks supérieurs rencontrait un problème avec un code qui fonctionnait et qui ne fonctionnait plus.
(Les noms de classe ont été modifiés pour protéger l’innocent, et je ne me souviens pas des noms exacts) Il avait du code C ++ qui écoutait les classes de messages entrants et les lisait. Auparavant, une classe de message était transmise et il y interagissait avec une variable pour déterminer le type de message. Il transmettrait alors le message en C-style comme une autre classe spécialisée qu’il aurait écrite et héritée de Message. Cette nouvelle classe avait des fonctions qui extrayaient les données comme il le voulait. Cela fonctionnait bien pour lui, mais ce n’était pas le cas maintenant.
Après de nombreuses heures à parcourir son code, il ne voyait aucun problème et j’ai jeté un coup d’œil par-dessus son épaule. Immédiatement, je lui ai dit que ce n’était pas une bonne idée de lancer Message dans le style C à une classe dérivée, ce qui n’était pas le cas. Il était en désaccord avec moi et a dit qu’il le faisait depuis des années et que si c’était faux, alors tout ce qu’il fait est faux, car il utilise fréquemment cette approche. Il a ensuite été appuyé par un entrepreneur qui m’a dit que j’avais tort. Ils ont tous deux fait valoir que cela fonctionne toujours et que le code n’a pas changé, de sorte que ce n’est pas cette approche mais quelque chose qui a violé son code.
J’ai regardé un peu plus loin et j’ai trouvé la différence. La dernière version de la classe Message avait une fonction virtuelle et n’avait jamais utilisé le virtuel. J’ai dit aux deux personnes qu’il y avait maintenant une table virtuelle et que les fonctions étaient recherchées, etc., etc., et que cela posait problème, etc., etc. Ils ont fini par accepter et on m’a présenté un commentaire que je n’oublierai jamais: “La virtualité bloque complètement le polymorphism et la programmation orientée object”.
Je leur ai fait parvenir une copie d’un motif de décorateur pour illustrer comment append une fonction à une classe existante, mais je n’ai rien entendu en retour. Comment ils ont corrigé l’idée, je n’en ai aucune idée.
Un mot: les macros. Je ne dis pas que les macros n’ont aucune place en C ++, mais les anciens programmeurs C ont tendance à les utiliser beaucoup trop après avoir basculé en C ++.
Utilisation de moulages de style C.
C ++ vous permet de choisir indépendamment d’autoriser les conversions entre types non liés et de modifier volatile
qualificatifs const
et volatile
, ce qui améliore considérablement la sécurité du type à la compilation par rapport à C. Il offre également des transmissions totalement sécurisées au prix d’une exécution. vérifier.
Les conversions en style C, les conversions non contrôlées entre presque tous les types, autorisent des classes entières d’erreur facilement identifiables par des conversions plus ressortingctives. Leur syntaxe les rend également très difficiles à rechercher, si vous souhaitez auditer le code source d’erreurs pour des conversions douteuses.
Écrire en using namespace std
car tout le monde le fait et ne réfléchit jamais sur sa signification. Ou savoir ce que cela signifie, mais dire ” std::cout << "Hello World" << std::endl;
air moche".
Passer des objects avec des pointeurs au lieu de références. Oui, vous avez encore parfois besoin de pointeurs en C ++, mais les références étant plus sûres, vous devez les utiliser quand vous le pouvez.
En supposant que lesdits programmeurs aient déjà commis l’erreur d’essayer d’apprendre le C ++:
Rendre tout dans une classe publique. Ainsi, les membres de données qui devraient être privés ne le sont pas.
Pas complètement comprendre la sémantique des pointeurs et des références et quand utiliser l’un ou l’autre. En ce qui concerne les pointeurs, le problème est également de ne pas gérer correctement la mémoire allouée dynamic ou d’échouer à utiliser des constructions “plus intelligentes” pour cela (par exemple, les pointeurs intelligents).
Mon préféré est le programmeur C qui écrit une seule méthode avec plusieurs arguments facultatifs.
Fondamentalement, la fonction ferait différentes choses selon les valeurs et / ou la nullité des arguments.
Ne pas utiliser de modèles lors de la création d’algorithmes et de structures de données ( exemple ). Cela rend les choses trop localisées ou trop génériques
Ie écrit
void qsort(MyStruct *begin, size_t length); //too localized void qsort(void *begin, size_t length, size_t rec_size, int(compare*)(void*,void*)); //too generic
au lieu de
template void qsort(RA_Iter begin, size_t length); //uses RA_Iter::value_type::operator< for comparison
Bien, une mauvaise conception de programme transcende les langages (castes, ignorant les avertissements, magie des précomstackurs non nécessaire, bidouillage inutile, ne pas utiliser les macros de classification des caractères), et le langage C lui-même ne crée pas trop de “mauvaises habitudes” (Ok, Macros, des âges de pierre), et de nombreux idiomes traduisent directement. Mais quelques-uns qui pourraient être considérés:
Utiliser une fonctionnalité simplement parce qu’elle est en C ++ et donc que cela doit être la bonne façon de faire quelque chose. Certains programmes n’ont tout simplement pas besoin d’inheritance, de MI, d’exceptions, de RTTI, de modèles (bien qu’ils soient … la charge de débogage est lourde), ou de choses de classe virtuelle.
S’en tenir à un extrait de code de C, sans se demander si C ++ a un meilleur moyen. (Il y a une raison pour laquelle vous avez maintenant des fonctions de classe, privées, publiques, const (développées au-delà de C89), des classes statiques, des références.
Ne pas être familiarisé avec C ++ i / o lib (son BIG, et vous devez le savoir), et mélanger C ++ i / o et C i / o.
Il pense que C ++ est un langage un peu plus différent de C. Il continuera à programmer C masqué par C ++. Pas d’utilisation avancée des classes, les structures sont considérées comme moins puissantes que les classes, les espaces de noms, les nouveaux en-têtes, les modèles, aucun de ces nouveaux éléments n’est utilisé. Il continuera à déclarer des entiers vars sans int, il ne fournira pas de fonctions prototypes. Il utilisera malloc et des pointeurs libres et dangereux, ainsi que des pré-processeurs, pour définir des fonctions inline. Ceci est juste une petite liste;)
Utilisations confuses de structures et de classes, surutilisation de méthodes globales prenant les pointeurs d’object comme arguments et pointeurs d’instance accessibles globalement
extern Application* g_pApp; void RunApplication(Application* app, int flags);
Aussi (ne dis pas que c’est totalement inutile, mais quand même):
const void* buf;
Déclarer toutes les variables au début de la fonction même si la variable ne sera utilisée qu’après 100 lignes environ.
Cela se produit surtout pour les variables locales déclarées dans une fonction.
Ne pas laisser assez seul et utiliser C à la place.
Résoudre le problème au lieu de créer une monstruosité basée sur la classe vous garantira de restr dans l’assurance maladie et les avantages 401K.
Implémenter lisp dans un seul fichier et en faire la conception.
Écrire des fonctions lisibles normales au lieu de remplacer des opérateurs?
Écrire dans un style compréhensible pour les programmeurs débutants qui considèrent les bonnes pratiques comme “ne pas écrire en C ++”.
Parler à l’OS dans sa propre langue.