C et C++ permettent d'avoir plus de contrôle sur le matériel
C et C++ vous permettent d'écrire du code très efficace
Les langages C et C++ sont portables
C et C++ sont des langages qui évoluent
C et C++ sont largement utilisés
C++ a peut-être de l'avenir, mais je doute que ça soit le cas de C
C a peut-être de l'avenir, mais je doute que ça soit le cas de C++
Je pense qu'ils n'ont plus beaucoup d'années devant eux
Autre (à préciser)
Pas d'avis
Exemple :
Car.h:
Wheel.h:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 #ifndef HEADERFILE_CAR #define HEADERFILE_CAR using namespace std; class Car; #include "Wheel.h" class Car { private: Wheel wheels[4]; public: Car(); }; #endif
Car.cpp:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 #ifndef HEADERFILE_WHEEL #define HEADERFILE_WHEEL using namespace std; class Wheel; #include "Car.h" class Wheel { private: double size; Car* onCar; public: Wheel(); Wheel( double aSize, Car* car); }; #endif
Wheel.cpp:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 #include "Car.h" Car:Car() { for (int iWheel=0; iWheel<4; iWheel++) { wheels[iWheel] = Wheel( 17, this); } };
main.cpp:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11 #include "Wheel.h" Wheel:Wheel() { size = 0.0; onCar = 0; }; Wheel:Wheel(double aSize, Car* car) { size = aSize; onCar = car; };
"Car.h" dépend de "Wheel.h" et vice-versa. Graphe cyclique des interfaces des modules. No warning du compilateur => catastrophe sur les projets. La même chose est également possible en Java. Tout langage digne de ce nom doit interdire les dépendances cycliques. C'est amusant que ce soit moi qui doivent vous enseigner les défauts de votre environnement favori. Sur les vrais projets, je vois des cycles sur 20, 30 modules. Une vraie catastrophe. Et à démêler tout cela, un budget refactoring monstrueux.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 #include <stdio.h> #include <stdlib.h> #include "Car.h" int main() { Car car(); printf("new car is made! \n"); }
CQFD. Passez à autre chose, votre outil ne vaut pas un clou.
PS. Je ne trolle pas, mais je vous donne des arguments détaillés, expliqués, chiffrés. Vous n'avez même pas la politesse de les vérifier vous-même. Clairement, vous n'avez aucune maîtrise du langage que vous prétendez défendre, vu votre incapacité à comprendre ne serait-ce que ses défauts les plus évidents. Si j'avais à auditer vos projets, que ne trouverai-je pas????
Le C++ n'empêche généralement pas les dépendances cycliques, mais tu viens de choisir un mauvais exemple.
Avec GCC, si j'essaie de compiler Wheel.cpp, j'ai l'erreur de compilation suivante :
error: field 'wheels' has incomplete type 'Wheel [4]'
Wheel.cpp fait #include "Wheel.h".
Wheel.h définit la macro HEADERFILE_WHEEL puis fait class Wheel; puis #include "Car.h".
Car.h fait #include "Wheel.h" qui n'a aucun effet car la macro HEADERFILE_WHEEL est définie. Donc le type Wheel n'est toujours pas un type complet.
Dans Car.h, on tombe alors sur Wheel wheels[4];, qui ne peut compiler que si Wheel est un type complet, car le compilateur a besoin de connaître sizeof(Wheel).
Remarque : Il y a aussi d'autres problèmes qui empêchent le code de compiler, comme Wheel:Wheel au lieu de Wheel::Wheel.
En résumé, d'après les propres dires des défenseurs du C++ qui se sont exprimés sur le forum:
- le C++ permet des cycles de dépendances, ce qui est très préjudiciable dès qu'il faut maintenir un projet de taille normale,
- le C++ est inutilisable par des étudiants en 1ere année, il ne devrait pas leur être enseigné,
- le C++ est inutilisable par des spécialistes de la haute disponibilité et de la haute fiabilité, car certaines constructions parfaitement sûres en Ada deviennent très dangereuses en C++,
- le C++ est très long à la compilation, dès qu'il y a beaucoup de .h, et des inlines dans le .h,
- le C++ est impropre au développement Agile, car il compile trop lentement, sauf à précompiler les entêtes, et en nombre limité, mais on retombe sur le problème du graphe cyclique des dépendances,
- le C++ manque de certaines caractéristiques très importantes, comme l'approche composant, les propriétés, etc.,
- si on veut développer avec sécurité (des intervalles), alors on perd la lisibilité, déjà qu'on en avait pas beaucoup...
- le C++ n'est pas lisible par les clients,
- les développeurs C++ sont condamnés en Europe par la concurrence asiatique.
Il me semble que le dossier est bien rempli. La plupart des remarques sont également applicables à Java (en particulier le graphe de dépendances). Au vu de ce dossier, je vous invite à regarder les alternatives et à laisser tomber C++ et Java. S vous ne pouvez pas accepter Pascal ou Ada, que j'ai simplement utilisés à titre d'exemple, il y a de nombreux autres langages qui ont de belles propriétés. Ou prenez une combinaison de langages...
Bien cordialement,
ThierryC
???
Avec un compilateur qui respecte le standard C++, il est impossible que ce code compile. Quand le compilateur tombe sur la variable membre Wheel wheels[4];, il a besoin de connaître la taille en bytes du type Wheel.
Quel compilateur utilises-tu ? Es-tu sûr que tu as compilé exactement le code que tu viens de publier ?
J'utilise gcc 5.4.0 sur Ubuntu 16.04. Ci-joint le code débogué. Désolé pour la première version livrée trop vite:
Car.h:
Wheel.h
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12 #ifndef HEADERFILE_CAR #define HEADERFILE_CAR using namespace std; class Car; #include "Wheel.h" class Car { private: Wheel* wheels[4]; public: Car(); }; #endif
Car.cpp:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14 #ifndef HEADERFILE_WHEEL #define HEADERFILE_WHEEL using namespace std; class Wheel; #include "Car.h" class Wheel { private: double size; Car* onCar; public: Wheel(); Wheel( double aSize, Car* car); }; #endif
Wheel.cpp:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 #include "Car.h" Car::Car() { for (int iWheel=0; iWheel<4; iWheel++) { wheels[iWheel] = new Wheel(); } };
et le main.cpp:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11 #include "Wheel.h" Wheel::Wheel() { size = 0.0; onCar = 0; }; Wheel::Wheel(double aSize, Car* car) { size = aSize; onCar = car; };
Je confirme : pas de vérification du graphe de dépendances par le compilateur C++.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 #include <stdio.h> #include <stdlib.h> #include "Car.h" int main(int argc, char** argv) { Car car(); printf("new car is made! \n"); }
Evidemment que le compilateur considère cette dépendance mutuelle comme valide puisque vous la lui demandez explicitement avec les "class Car;" et "class Wheel;". C'est même une fonctionnalité très pratique dans les MVC pour permettre des appels mutuels entre certains composants. Par défaut, cette dépendance n'est pas permise par le compilateur, ce qui ne pose donc pas de problème particuliers.
Je ne suis pas choqué qu'un langage interdise les dépendances circulaires entre modules, tant qu'un module peut contenir plusieurs classes, par exemple un conteneur et ses itérateurs. Je pense que c'est une bonne chose.
Si plusieurs modules forment un petit cycle, alors ils peuvent être regroupés en un seul module.
Si plusieurs modules forment un grand cycle, alors il y a un problème de conception.
Cela dit, si les développeurs d'un projet ont besoin d'un tel contrôle du compilateur pour améliorer la qualité du code, cela signifie qu'il y a un problème de gestion derrière, par exemple une pression pour faire du quick & dirty et un manque de revue de code par les pairs. Or, dans de telles conditions, même si certains langages empêchent mieux certaines bêtises que d'autres, la qualité du code sera toujours mauvaise à la fin.
Ce que vous dites est complétement idiot : un compilateur n'est pas censé accepter n'importe quelle c...ie écrite par le développeur. Cette dépendance devrait être interdite tout le temps et sans exception par le compilateur quelles que soient les pseudo-raisons invoquées par le développeur. C'est au développeur de s'adapter aux contraintes du respect de la non-cyclicité du graphe de dépendances. Il y a de nombreux moyens pour cela, dont, par exemple, l'inversion des dépendances...
Votre explication montre en plus que vous n'avez aucune connaissance de la construction de grands logiciels. Je vous invite à relire Booch, qui reste le meilleur auteur sur le sujet. Si jamais j'avais à auditer un de vos logiciels, cela ne devrait pas être piqué des hannetons, comme on dit....
Bien cordialement,
ThierryC
il n'y a pas de dépendances circulaires dans UN module, si par exemple celui-ci déclare une classe et ses itérateurs. Le sujet est bien la dépendance cyclique ENTRE modules, entre unités de compilation. C'est l'une des grandes erreurs de Java d'avoir confondu la classe avec l'unité de compilation, le module. Grosse erreur.
Je vous en prie, programmez en assembleur, il n'y a aucun contrôle, et vous pourrez faire ce que vous voulez... voyez-vous, c'est une démonstration par l'absurde. Au contraire, plus le compilateur est de haut niveau, plus il vérifie ce que vous faites dès la compilation, moins vous avez de soucis et plus vous vous concentrez sur le besoin utilisateur, et plus vous écrivez un source de bonne qualité, qui était déjà de bonne qualité à la base. L'assurance qualité, le contrôle qualité, le contrôle du compilateur, la vérification de la dette technique ne permettent pas à des mauvais développeurs de bien programmer, mais à de bons programmeurs d'aller bien et vite sans se soucier des détails, et de rattraper rapidement un petit dérapage très occasionnel.
J'ai entendu cet argument maintes fois que l'assurance qualité, le contrôle qualité et le contrôle du compilateur étaient inutiles, pour tous ces projets gérés par de magnifiques développeurs C++. Cet argument fait plaisir au management en plus, qui en profite pour rogner sur les budgets. Et pourquoi faire des tests? Après tout, on programme bien. Et hop, les tests sautent aussi, avec leur budget. A la fin, il ne reste rien, que du code mal fait, à jeter quand quelqu'un est devenu suffisamment lucide. (Et que le manager a été promu vers de nouvelles aventures....)
Cordialement,
ThierryC
À propos des contrôles du compilateur, il faut distinguer ceux qui repèrent les erreurs d'étourderies de ceux qui essaient d'empêcher de mal concevoir. Les premiers servent pour tout le monde. Les autres servent surtout à empêcher ceux qui codent à court terme de trop casser le projet.
Par exemple, le typage fort permet, entre autres, de repérer des erreurs d'étourderies directement à la compilation. De mon point de vue, ne pas supporter le typage fort est un gros défaut.
Par contre, restreindre l'héritage multiple et empêcher les dépendances circulaires entre modules, ça sert surtout à empêcher ceux qui codent à court terme de trop casser le projet. Quand un langage est trop permissif à ces niveaux, je considère cela aussi comme des défauts du langage, mais dont l'impact sur la productivité n'est significatif que s'il y a déjà un problème de gestion derrière.
Il me semble que la "philosophie" de C++ est de ne pas prendre le développeur pour un imbécile. Le typage fort détecte des erreurs certaines donc oui c'est à utiliser. Par contre que le compilateur n'autorise pas les dépendances circulaires par défaut mais les permettent si le dev les demandent explicitement, je ne vois pas le problème. Tous les projets n'ont pas 20 millions de loc à maintenir pour 30 ans, donc je trouve pratique d'avoir cette fonctionnalité pour certaines situations même si elle est déconseillée pour d'autres. Idem pour l'héritage multiple de classes voire le diamant.
Vous changez de sujet. La récursivité n'est pas interdite en général. Uniquement sur les projet où la sécurité est critique. Je vois que vous ne connaissez pas les règles de bonne programmation, comme par exemple SQALE, ou A2DAM de l'Agile Alliance. Cela vous ferait le plus grand bien.
Pour en revenir au graphe de dépendances, il doit être acyclique. C'est une règle de bonne programmation qui ne souffre pas d'exception. Quand vous la violez, non seulement vous vous mettez mal auprès de tous les auditeurs, mais vous ne devez pas en rencontrer beaucoup, mais en plus, cela augmente vos difficultés de maintenance...
J'ai déjà entendu ça : "it's not a bug, it's a feature".
Non, ces caractéristiques du langage C++ sont des défauts, et ils ne permettent pas à des développeurs moustachus, comme vous, peut-être, d'utiliser une astuce pour allez plus vite, mais, en revanche, ils permettent à la majorité des développeurs C++ de se planter... en beauté. Par ailleurs, pour avoir fait de gros projets, sans graphe de dépendances cycliques, on peut faire tous les trigrammes que vous voulez, y compris le MVC.
Sinon, voilà un autre point d'acquis, d'après vous : C++ est pour les petits projets... pour les gros, s'abstenir. On avance. C'est bien.
Je pense qu'il y a un malentendu.
On peut vouloir une double dépendance entre deux classes : une classe A connaît une classe B qui connaît aussi la classe A.
Dans un langage qui interdit les dépendances circulaires entre modules, on mettra les deux classes A et B dans le même module.
Ainsi, on peut à la fois avoir de petits cycles de dépendances entre classes et ne pas avoir de dépendances circulaires entre modules.
Par contre, si on a un très gros cycle de dépendances entre classes, alors il y a un problème d'architecture.
linux 19 millions de lignes de C
LLVM 4 millions de lignes de C++
en 2014 GCC 14.5 millions de lignes de C, ils ont annoncé qu'ils passaient au c++.
Webkit 12.5 millions de lignes la plupat en C++
Chromium 8.5 millions de lignes de C++, 1.6 millions de ligne de C
franchement vous vous rendez compte de ce que vous dites?
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager