La différence entre C ++ et Java réside dans ce que les langages considèrent comme leur plus petite unité de liaison.
Parce que C a été conçu pour coexister avec l'assemblage, cette unité est le sous-programme appelé par une adresse. (Cela est vrai pour d'autres langages qui se compilent dans des fichiers objets natifs, tels que FORTRAN.) En d'autres termes, un fichier objet contenant une fonction foo()
aura un symbole appelé _foo
qui sera résolu en une adresse telle que0xdeadbeef
lors de la liaison. C'est tout ce qu'il y a. Si la fonction doit prendre des arguments, c'est à l'appelant de s'assurer que tout ce que la fonction attend est en ordre avant d'appeler son adresse. Normalement, cela se fait en empilant des choses sur la pile, et le compilateur s'occupe du travail de grognement et s'assure que les prototypes correspondent. Il n'y a aucune vérification de ceci entre les fichiers d'objets; si vous supprimez la liaison d'appel, l'appel ne se déclenchera pas comme prévu et vous n'obtiendrez pas d'avertissement à ce sujet. Malgré le danger, cela permet de lier les fichiers objets compilés à partir de plusieurs langues (y compris l'assemblage) dans un programme fonctionnel sans trop de tracas.
C ++, malgré toutes ses fantaisies supplémentaires, fonctionne de la même manière. Le compilateur chausse les espaces de noms, les classes et les méthodes / membres / etc. dans cette convention en aplatissant le contenu des classes en noms uniques qui sont mutilés de manière à les rendre uniques. Par exemple, une méthode comme Foo::bar(int baz)
pourrait être altérée _ZN4Foo4barEi
lorsqu'elle est placée dans un fichier objet et une adresse comme 0xBADCAFE
lors de l'exécution. Cela dépend entièrement du compilateur, donc si vous essayez de lier deux objets qui ont des schémas de manipulation différents, vous n'aurez pas de chance. Aussi laid que cela soit, cela signifie que vous pouvez utiliser un extern "C"
bloc pour désactiver la manipulation, ce qui permet de rendre le code C ++ facilement accessible dans d'autres langages. C ++ a hérité de la notion de fonctions flottantes de C, en grande partie parce que le format d'objet natif le permet.
Java est une bête différente qui vit dans un monde isolé avec son propre format de fichier objet, le .class
fichier. Les fichiers de classe contiennent une multitude d'informations sur leur contenu qui permet à l'environnement de faire des choses avec les classes au moment de l'exécution dont le mécanisme de liaison natif ne pouvait même pas rêver. Cette information doit commencer quelque part, et ce point de départ est leclass
. Les informations disponibles permettent au code compilé de se décrire sans avoir besoin de fichiers séparés contenant une description dans le code source comme vous le feriez en C, C ++ ou dans d'autres langages. Cela vous donne tous les types de langages d'avantages de sécurité utilisant le manque de liaison natif, même au moment de l'exécution, et c'est ce qui vous permet de pêcher une classe arbitraire dans un fichier en utilisant la réflexion et de l'utiliser avec un échec garanti si quelque chose ne correspond pas .
Si vous ne l'avez pas déjà compris, toute cette sécurité s'accompagne d'un compromis: tout ce que vous liez à un programme Java doit être Java. (Par «lien», je veux dire à chaque fois que quelque chose dans un fichier de classe fait référence à quelque chose dans un autre.) Vous pouvez lier (au sens natif) au code natif à l'aide de JNI , mais il existe un contrat implicite qui dit que si vous cassez le côté natif , vous possédez les deux pièces.
Java était grand et pas particulièrement rapide sur le matériel disponible lors de son introduction, un peu comme Ada l'avait été au cours de la décennie précédente. Seul Jim Gosling peut dire avec certitude quelles étaient ses motivations pour créer la plus petite unité de liaison de la classe Java, mais je devrais deviner que la complexité supplémentaire qu'aurait ajoutée l'ajout de flottants libres à l'exécution aurait pu être un tueur de deal.