Der Unterschied zwischen C ++ und Java besteht darin, was die Sprachen als kleinste Verknüpfungseinheit betrachten.
Da C für die Koexistenz mit der Assembly konzipiert wurde, ist diese Unit die von einer Adresse aufgerufene Unterroutine. (Dies gilt auch für andere Sprachen, die in systemeigene Objektdateien kompiliert werden, z. B. FORTRAN.) Mit anderen Worten, eine Objektdatei, die eine Funktion enthält foo()
, hat ein Symbol mit dem Namen _foo
, das in nichts anderes als eine Adresse wie aufgelöst wird0xdeadbeef
während der Verlinkung. Das ist alles was es gibt. Wenn die Funktion Argumente annehmen soll, muss der Aufrufer sicherstellen, dass alles, was die Funktion erwartet, in Ordnung ist, bevor er ihre Adresse aufruft. Normalerweise werden dazu Dinge auf den Stapel gestapelt, und der Compiler kümmert sich um die Grunzarbeit und stellt sicher, dass die Prototypen übereinstimmen. Dies wird zwischen den Objektdateien nicht überprüft. Wenn Sie die Anrufverknüpfung vermasseln, läuft der Anruf nicht wie geplant ab und Sie erhalten keine Warnung. Trotz der Gefahr können so aus mehreren Sprachen kompilierte Objektdateien (einschließlich Assembler) ohne großen Aufwand zu einem funktionsfähigen Programm zusammengefügt werden.
C ++ funktioniert trotz aller zusätzlichen Fantasie genauso. Der Compiler erkennt Namespaces, Klassen und Methoden / Member / etc. in diese Konvention einfließen, indem der Inhalt von Klassen in einzelne Namen reduziert wird, die auf eine Weise verkürzt werden, die sie einzigartig macht. Zum Beispiel Foo::bar(int baz)
könnte eine Methode wie in entstellt werden, _ZN4Foo4barEi
wenn sie in eine Objektdatei und eine Adresse wie 0xBADCAFE
zur Laufzeit gestellt wird. Dies hängt vollständig vom Compiler ab. Wenn Sie also versuchen, zwei Objekte mit unterschiedlichen Verwirrungsschemata zu verknüpfen, haben Sie Pech. So hässlich dies ist, bedeutet dies, dass Sie einen extern "C"
Block verwenden können, um das Mangeln zu deaktivieren, wodurch es möglich wird, C ++ - Code für andere Sprachen leicht zugänglich zu machen. C ++ hat die Idee der frei schwebenden Funktionen von C geerbt, hauptsächlich weil das native Objektformat dies zulässt.
Java ist ein anderes Biest, das in einer isolierten Welt mit seinem eigenen Objektdateiformat, der .class
Datei , lebt . Klassendateien enthalten eine Fülle von Informationen zu ihren Inhalten , die es der Umgebung ermöglichen, zur Laufzeit Dinge mit Klassen zu tun, von denen der systemeigene Verknüpfungsmechanismus nicht einmal träumen konnte. Diese Information muss irgendwo beginnen, und dieser Ausgangspunkt ist derclass
. Die verfügbaren Informationen ermöglichen es dem kompilierten Code, sich selbst zu beschreiben, ohne dass separate Dateien mit einer Beschreibung im Quellcode wie in C, C ++ oder anderen Sprachen erforderlich sind. Das gibt Ihnen alle Arten von Sicherheitsvorteilen, die Sprachen mit dem nativen Verknüpfungsmangel erzielen, selbst zur Laufzeit, und ermöglicht es Ihnen, eine beliebige Klasse mit Reflection aus einer Datei zu fischen und sie mit einem garantierten Fehler zu verwenden, wenn etwas nicht übereinstimmt .
Wenn Sie es noch nicht herausgefunden haben, bringt all diese Sicherheit einen Kompromiss mit sich: Alles, was Sie mit einem Java-Programm verknüpfen, muss Java sein. (Mit "verknüpfen" meine ich, wann immer sich etwas in einer Klassendatei auf etwas in einer anderen Datei bezieht.) Sie können mit JNI (im systemeigenen Sinne) auf systemeigenen Code verlinken , aber es gibt einen impliziten Vertrag, der besagt, dass Sie die systemeigene Seite unterbrechen Sie besitzen beide Stücke.
Java war groß und nicht besonders schnell auf der verfügbaren Hardware, als es zum ersten Mal eingeführt wurde, ähnlich wie Ada es im vorigen Jahrzehnt getan hatte. Nur Jim Gosling kann mit Sicherheit sagen, was seine Motivation war, um die kleinste Verbindungseinheit der Klasse Java herzustellen, aber ich muss vermuten, dass die zusätzliche Komplexität, die das Hinzufügen von Streubesitzern zur Laufzeit beigetragen hätte, ein Deal-Killer gewesen sein könnte.