Il y a déjà de bons points dans d'autres réponses, mais j'aimerais apporter une réponse plus complète, en répondant à vos questions et à vos déclarations individuellement.
Si Java ne fournit pas une fonctionnalité dont dispose le C ++, cela signifie que la fonctionnalité n'est pas bonne, nous devons donc empêcher son utilisation.
Cela a été assez bien répondu: Java n'est pas "la bonne partie" de C ++, et il n'y a aucune raison de le penser.
En particulier, bien que les mérites de chaque fonctionnalité C ++ individuelle soient discutables, de nombreuses fonctionnalités de C ++ 11 / C ++ 14 qui ne font pas partie de Java ne sont pas nécessairement exclues car les concepteurs Java pensaient qu’elles étaient une mauvaise idée. À titre d’exemple, jusqu’à la version 8, Java n’avait pas de lambda, mais ils ont été introduits au C ++ dans la norme C ++ 11. Avant Java 8, votre hypothèse selon laquelle les fonctionnalités C ++ manquantes dans Java étaient absentes de par leur conception, car elles ne sont "pas bonnes" aurait laissé entendre que lambdas en tant que fonctionnalité de langage n'est "pas bon" (à la grande horreur des LISPers, probablement assez horrifié d'apprendre que vous semble réellement comme Java). Mais maintenant, les concepteurs Java ont mis leur Stamp of Approval (TM) sur les lambdas, ils sont donc maintenant une bonne chose.
Pour aller un peu plus loin, même dans Java 8, les lambdas-as-closures ne sont pas aussi flexibles que les lambdas de C ++ 14, mais cela peut être dû aux limitations de l'architecture de la machine virtuelle Java plutôt qu'à une décision consciente que l'approche plus flexible est mauvaise pour un client. perspective de conception de la langue.
Le code C ++ avec des fonctionnalités spécifiques à C ++ (par exemple, les fonctions ami, l'héritage multiple) ne peut être maintenu ou révisé que par les programmeurs C ++, mais si nous écrivons simplement C ++ comme Java (sans fonctionnalité spécifique au langage C ++), le code peut être maintenu ou révisé par les deux. Programmeurs C ++ et Java.
C'est la principale chose à laquelle je voulais réagir.
De manière générale, il peut être intéressant d'obtenir des critiques de code de programmeurs qui ne connaissent pas très bien le langage que vous utilisez. Ils peuvent vous donner de précieux commentaires sur la clarté de vos noms et commentaires de fonction / méthode, et (comme votre question l’implique correctement), si la langue est similaire à une ou plusieurs langues qu’ils connaissent déjà, ils pourront peut-être suivre le flux de base du programme. et potentiellement attraper des erreurs de logique.
Cependant, il est pas le cas que ce genre d'examen ne sera jamais « aussi bien que » ou « équivalent à » examen des développeurs qui savent en fait la langue que vous utilisez. Cela est essentiellement dû au fait que donner à une langue l' apparence d'une autre dissimulera en général des différences subtiles, tandis que se faire se comporter comme une autre (en particulier dans le cas de C ++ et de Java) peut être non idiomatique pour le langage et / ou peut-être encore trop déroutant pour les relecteurs.
Tout d’abord, réfléchissons à ce que cela signifierait de faire en sorte que C ++ "ressemble" à Java. Comme un cas simple, vous pouvez utiliser new
pour instancier des objets, comme en Java:
Foo foo = new Foo();
Mais les objets instanciés de cette façon utilisent ->
au lieu d' .
appeler des méthodes, donc si vous voulez que les appels de méthode ressemblent à Java, vous devez plutôt écrire:
Foo& foo = *new Foo();
Mais cela n’est pas idiomatique; en particulier, la mémoire doit ensuite être nettoyée à l'aide d' un codedelete &foo
que certains développeurs expérimentés en C ++ pourraient même ne pas comprendre . De toute façon, il y a de drôles de symboles non-Java qui parsèment, donc nous ne pouvons pas vraiment faire en sorte que le langage "ressemble" à Java. (Vous pouvez éliminer en *new
utilisant #define New *new
, ou, pire, #define new *new
mais ensuite vous implorez simplement que vos collègues développeurs vous haïssent.) Et, comme mentionné ci-dessus, delete
n'existe pas en Java, donc dans tous les cas (comme mentionné dans une autre réponse ) vous ne pouvez pas vraiment faire en sorte que l’utilisation des objets ressemble à celle qu’elle a en Java sans fuites de mémoire.
Mais le C ++ moderne inclut des pointeurs partagés intelligents, qui se comportent beaucoup comme les références de variable gérées par la mémoire de Java. Donc, partout en Java que vous pourriez écrire Foo foo = new Foo();
, vous pouvez écrire:
std::shared_ptr<Foo> foo = std::make_shared<Foo>();
Vous utilisez maintenant une fonctionnalité de langage qui ressemble beaucoup à Java sous le capot. Mais tout à coup, vous avez beaucoup à expliquer aux relecteurs non-C ++: qu'est-ce que c'est shared_ptr
? Quels sont les subtils "pièges" de make_shared
? (Il utilise une transmission parfaite, qui présente certains cas d'échec et peut conduire à l'appel du "mauvais" constructeur.) Pourquoi les méthodes doivent-elles être appelées avec ->
, mais l'utilisation .
de certaines méthodes est autorisée par le compilateur? ( shared_ptr
a ses propres méthodes.) Si la méthode Foo::reset(void)
existe, un développeur non averti peut essayer de l'appeler foo.reset()
, qui (s'il n'y a qu'un seul pointeur partagé pointant vers cette instance ou Foo
lorsque l'appel a lieu) supprimera la mémoire sous-jacente et sera annulée foo
, et Les développeurs Java ne risquent pas d'attraper ce problème.
De plus, C ++ a beaucoup de pièges qui sont spécifiques à la langue. Autant que je sache, la plupart des développeurs C ++ apprennent à gérer ces écueils en développant progressivement leur propre langage pour des pratiques C ++ "sûres", ce qui est souvent assez unique pour eux ou pour leur équipe de développement (voir par exemple la réponse existante qui mentionne la Les pratiques de codage de Google et le commentaire à ce sujet indiquant que "les vétérans chevronnés du C ++ rejettent généralement les directives de codage de Google"). Toutes les affirmations selon lesquelles le langage pourrait être trop compliqué, semble-t-il (selon mon expérience, au moins), se heurtent généralement à une variation de "bien, arrêtez de le mal utiliser". Je sais que cela est une vue très négative de la communauté C ++, et il y a certainement des développeurs expérimentés plus disposés à aider les apprenants langue, mais il ne semble être une certaine attitude défensive vis-à-vis, par exemple, d’un comportement indéfini (voir par exemple une grande partie de la discussion dans le lien «pièges» ci-dessus).
Les développeurs Java ne seront tout simplement pas utiles pour trouver et corriger ces pièges via la révision du code.
On vous demandera peut-être de convertir le code en Java un jour.
Il est tout à fait valable - même louable - d'essayer de prendre en compte ce qui pourrait arriver à votre code à l'avenir pendant la phase de conception.
Mais, premièrement, cette considération particulière semble être une possibilité lointaine: le code est généralement soit réutilisé tel quel (par exemple, vous pouvez brancher tout ou partie du code C ++ actif dans un logiciel Java futur utilisant une interface JNI), ou le réécrire entièrement à la place. que directement manuellement "transcrit".
Et, deuxièmement, vous dites plus tard:
Chaque fonctionnalité spécifique au langage C ++ (par exemple: l'héritage multiple) devrait avoir des alternatives à implémenter en Java ....
Cela annule essentiellement votre point "converti en Java". Si le logiciel est écrit en C ++ idiomatique puis converti en Java idiomatique, il n’ya aucune raison de s’attendre à ce que cette conversion soit (ou pourrait!) Être réalisée en appliquant un mappage précis un à un des fonctionnalités C ++ aux fonctionnalités Java.
Le code sans fonctionnalités spécifiques à C ++ est généralement plus facile à gérer.
Vous ne comprenez pas ce que vous voulez dire ici, mais je suis en quelque sorte d’accord avec une partie de ceci: à moins que vous ne soyez très prudent, et même lorsque vous êtes prudent, les fonctionnalités C ++ peuvent entraîner des problèmes de maintenabilité. Le C ++ FQA Lite (un site Web critique du langage et de ses adeptes de quelqu'un qui semble au moins le comprendre assez bien) déclare que
... 80% des développeurs comprennent au plus 20% du langage. Ce n'est pas la même chose pour 20%, alors ne comptez pas sur eux pour comprendre le code de chacun.
VEUILLEZ NOTER: Si vous êtes un fan de C ++ et que vous répondez à ce point dans ma réponse, vous êtes enclin à passer directement aux commentaires pour faire valoir que l'auteur de la FQA ne comprend pas réellement le C ++ ou qu'il est fallacieux dans la plupart de ses arguments. , notez que (1) deux phrases exactement après que je le cite, je reconnais que la FQA est une source très partiale, et (2) peu importe ce que je veux dire si l’auteur de la FQA comprend ou non C ++ et je n'essaie pas de critiquer le C ++, et vous devriez lire le reste du message sans supposer que je suis anti-C ++ simplement parce que j'ai cité la FQA. Fin de la note.
De même, Linus Torvalds déteste le C ++ pour cette raison (avertissement: link implique beaucoup de jurons, dans le style tristement célèbre de Linus).
De toute évidence, ces questions sont très biaisées, mais même les partisans du C ++ disent souvent qu'il ne faut pas utiliser l'intégralité de l'ensemble des fonctionnalités du langage (à nouveau, reportez-vous aux consignes de codage de Google; Bjarne Stroustrup, créateur du C ++, par exemple). , a publiquement déclaré: "Dans C ++, il existe un langage beaucoup plus petit et plus propre qui a du mal à sortir").
Je pense donc que l’idée selon laquelle les fonctionnalités C ++ sont trop faciles à utiliser, en particulier si vous venez de l’arrière-plan Java, a du mérite. En outre, l’idée d’atténuer ces problèmes en se limitant à un sous-ensemble de la langue présente des avantages.
Cependant, décider quel sous-ensemble utiliser en utilisant un langage différent ne semble pas être la bonne approche, à moins que le "langage différent" soit C, car il existe vraiment un sous-ensemble du langage C ++ ressemblant à C. (Linus fait référence à cela dans son discours ci-dessus, et Scott Meyers appelle même ce sous-ensemble un "sous-langage".) Le paradigme d'exécution de Java (ramassé, fonctionnant sur une machine virtuelle) est tellement différent du C ++ qu'il est il n’est pas clair qu’il existe des leçons utiles à tirer de l’utilisation de C ++, et comme indiqué ci-dessus, essayer de tirer des leçons de C ++ directement à partir de Java peut conduire à un code très non idiomatique.
Au lieu de cela, essayez de définir votre "sous-ensemble acceptable" du langage sur une compréhension de la façon dont le langage peut être utilisé idiomatiquement. Si vous souhaitez un sous-ensemble assez restrictif qui tire toujours parti de nombreuses fonctionnalités de C ++ autres que celles proposées par C, la directive de codage susmentionnée de Google pourrait être un bon point de départ. Bien sûr, vous aurez des développeurs qui disent qu’il n’ya "pas d’argument rationnel" pour certaines restrictions de Google , mais à moins que vous ne cherchiez à engager Alexandrescu hors de son travail sur le langage D (qui devrait vous dire quelque chose), probablement d'accord. C'est certainement mieux que d'essayer de transformer le C ++ en Java.
Un autre bon point de départ pour un ensemble de directives de code est les nouvelles directives de base C ++ , un travail en cours de réalisation de Bjarne Stroustrup et Herb Sutter.
Le seul autre moyen de remédier aux faiblesses du C ++ consiste à choisir un langage différent. On dirait que vous aimez Java et que vous pensez qu'il est possible que ce projet soit éventuellement converti en Java. Comme indiqué dans une autre réponse, vous pouvez simplement ... commencer par Java.
Il y a deux raisons pour lesquelles vous pourriez vraiment avoir besoin d'utiliser autre chose que Java:
- Vous avez vraiment besoin des performances d'exécution. Dans ce cas, traiter le C ++ comme s'il s'agissait de Java ne vous aiderait probablement pas, car des techniques similaires à Java, telles que les pointeurs partagés, altèrent les performances d'exécution.
- Le logiciel doit fonctionner sur une plate-forme obscure qui ne prend pas encore en charge la machine virtuelle Java. Dans ce cas, vous êtes probablement coincé avec des langues ayant des interfaces GCC ou Clang. C et C ++ sont des candidats évidents, mais vous pouvez également examiner quelque chose comme Rust. (Prise rapide: je n'ai pas beaucoup utilisé Rust, mais il a l'air génial et j'ai hâte de travailler sur un projet majeur de Rust dès que je peux, et je pense que tous ceux qui envisagent de démarrer un projet C ++ devraient envisager Rust comme alternative.)
Chaque fonctionnalité spécifique au langage C ++ (par exemple: l'héritage multiple) devrait avoir des alternatives à implémenter en Java. Si ce n'est pas le cas, cela signifie que le modèle de conception ou l'architecture du code est problématique.
J'ai déjà abordé cette question un peu, mais j'ai intentionnellement omis votre deuxième phrase.
Je ne suis pas convaincu que quelque chose du genre constexpr
, ce qui n'aurait aucun sens dans un langage partiellement JIT comme Java, est une indication d'architecture invalide. Je suis plus ouvert à l'idée que l'utilisation excessive de la méta-programmation de gabarits puisse poser plus de problèmes qu'elle n'en vaut la peine, en particulier à l'heure constexpr
actuelle pour l'évaluation des fonctions au moment de la compilation, mais il est clair constexpr
qu'il n'y a pas de défaut de conception si utilisez-le: vous vous assurez simplement que certains calculs sont effectués avant même d'exécuter le code, ce qui représente un gain de performances impressionnant (voir, par exemple, cette entrée pour le problème à n corps de The Benchmark Game , qui surpasse toutes les entrées, sauf une autre écrit en C ++,