Frage

Viele Sprachen wie Java, C #, nicht gesonderte Erklärung von der Implementierung. C # hat ein Konzept der partiellen Klasse, aber die Umsetzung und Erklärung nach wie vor in der gleichen Datei.

Warum nicht C ++ das gleiche Modell hat? Ist es praktisch Header-Dateien zu haben?

Ich beziehe mich auf aktuelle und kommende Versionen von C ++ Standard.

War es hilfreich?

Lösung

Ich blättere routinemäßig zwischen C # und C ++, und das Fehlen von Header-Dateien in C # ist einer meiner größten Haustier ärgert. Ich kann in einer Header-Datei suchen und lernen, alles was ich brauche um eine Klasse zu wissen -, was es werden Member-Funktionen aufgerufen, ihre Aufruf-Syntax, etc. -. Ohne durch die Seiten des Codes waten, der die Klasse implementiert

Und ja, ich weiß, über partielle Klassen und #regions, aber es ist nicht das gleiche. Partielle Klassen tatsächlich machen das Problem noch schlimmer, weil eine Klassendefinition über mehrere Dateien verteilt. Soweit #regions gehen, sie scheinen nie in der Weise erweitert werden, ich möchte, was ich im Moment mache, so habe ich Zeit erweitert die kleinen und die verbringen, bis ich den Blick richtig zu machen.

Vielleicht, wenn Visual Studio Intellisense besser für C ++ gearbeitet, würde ich nicht einen zwingenden Grund habe zu verweisen, um Dateien an .h so oft, aber auch in VS2008, C ++ s

's IntelliSense kann nicht C # berühren'

Andere Tipps

Abwärtskompatibilität - Header-Dateien werden nicht beseitigt, weil es Abwärtskompatibilität brechen würde

.

Header-Dateien ermöglichen eine unabhängige Kompilierung. Sie brauchen nicht zugreifen oder auch die Implementierungsdateien haben, um eine Datei zu kompilieren. Dies kann leichter verteilt baut machen.

Auf diese Weise kann auch SDKs ein wenig leichter gemacht werden. Sie können nur die Header und einige Bibliotheken bieten. Es gibt natürlich Möglichkeiten, um dieses, die anderen Sprachen verwendet werden.

Auch Bjarne Stroustrup aufgerufen Header-Dateien eine Flickschusterei.

Aber ohne ein Standard-Binär-Format, die die notwendigen Metadaten (wie Java-Klassen-Dateien oder .NET PE-Dateien) enthält ich sehe keinen Weg, um die Funktion zu implementieren. Ein gestrippt ELF oder a.out binäre hat nicht viel von den Informationen, die Sie zu extrahieren benötigen würde. Und ich glaube nicht, dass die Informationen jemals in Windows XCOFF Dateien gespeichert werden.

, gibt Stroustrup einen Grund mehr, aus ...

Die gleiche Header-Datei können zwei oder mehr Umsetzungs Dateien haben, die gleichzeitig ausgearbeiteten auf, ohne die Notwendigkeit eines Quellensteuersystems um mehr als ein Programmierer werden kann.

Dies könnte in diesen Tagen scheint seltsam, aber ich denke, es war ein wichtiges Thema, wenn C ++ erfunden wurde.

C wurde einen Compiler leicht zu machen, zu schreiben. Es hat eine Menge Sachen auf der Grundlage dieser ein Prinzip. Pointers gibt es nur einen Compiler einfacher zu machen schreiben, als Dateien do Header. Viele der Dinge, die C ++ übertragen basiert auf Kompatibilität mit diesen Merkmalen zu erleichtern Compiler implementiert zu schreiben.

Es ist eine gute Idee eigentlich. Wenn C erstellt wurde, C und Unix waren irgendwie ein Paar. C portiert Unix, Unix lief C. Auf diese Weise C und Unix schnell von Plattform zu Plattform verbreiten könnte, während ein Betriebssystem auf Montage basiert musste komplett neu geschrieben werden portiert werden.

Das Konzept eine Schnittstelle in einer Datei anzugeben, und die Umsetzung in einer anderen ist keine schlechte Idee überhaupt, aber das ist nicht das, was C-Header-Dateien sind. Sie sind einfach eine Möglichkeit, die Anzahl der Durchgänge einen Compiler durch den Quellcode zu machen hat zu begrenzen und eine begrenzte Abstraktion des Vertrages zwischen Dateien zu ermöglichen, so dass sie miteinander kommunizieren können.

Diese Elemente, Zeiger, Header-Dateien, etc ... bieten nicht wirklich einen Vorteil gegenüber einem anderen System. Durch mehr Aufwand in die Compiler setzen, können Sie ein Referenzobjekt so leicht wie ein Zeiger auf den exakt gleichen Objektcode kompilieren. Dies ist, was C ++ funktioniert jetzt.

C ist eine große, einfache Sprache. Es hatte eine sehr begrenzte Feature-Set, und man konnte einen Compiler, ohne viel Aufwand schreiben. Portieren es ist in der Regel trivial! Ich versuche nicht, zu sagen, es ist eine schlechte Sprache oder nichts, es ist nur, dass C primäre Ziele, wenn es erstellt wurde Reste in der Sprache verlassen kann, die jetzt mehr oder weniger überflüssig sind, sondern werden für die Kompatibilität der Umgebung gehalten werden.


Es scheint, wie einige Leute nicht wirklich glauben, dass C-Port Unix geschrieben wurde, so hier: ( von )

  

Die erste Version von UNIX wurde geschrieben   in Assembler-Sprache, aber Thompson   Absicht war, dass es geschrieben werden würde   in einer Hochsprache.

     

Thompson zuerst im Jahr 1971 versucht, zu verwenden,   Fortran auf dem PDP-7, aber aufgab   nach dem ersten Tag. Dann schrieb er ein   sehr einfache Sprache, rief er B,   die er in Gang gekommen auf der PDP-7. Es   Probleme gearbeitet, aber es gab.   Erstens, weil die Umsetzung war   interpretiert, es würde immer   schleppend. Zweitens sind die Grundbegriffe von B,   die auf dem wortorientierten beruhte   BCPL, waren einfach nicht richtig für eine   byteorientierte Maschine wie die neue   PDP-11.

     

Ritchie verwendet, um die PDP-11-Typen hinzufügen   bis B, die für eine Weile genannt wurde NB   für „New B“, und dann fing er an zu   schreiben einen Compiler für sie. "So, dass die   erste Phase der C war wirklich diese beiden   Phasen in kurzer Aufeinanderfolge von, erstens,   einige Sprach Änderungen von B, wirklich,   die Art Struktur zu ändern, ohne zu   viel Veränderung in der Syntax; und tun   der Compiler „, sagte Ritchie.

     

„Die zweite Phase war langsamer“, sagte er   Umschreiben UNIX in C. Thompson   im Sommer 1972 begann, hatte aber   zwei Probleme: herauszufinden, wie laufen   die grundlegenden Co-Routinen, das heißt, wie man   Schaltersteuerung von einem Prozess zum   Ein weiterer; und die Schwierigkeiten bei der   die richtige Datenstruktur, da die   Original-Version von C nicht über   Strukturen.

     

"Die Kombination der Dinge verursacht   Ken zu geben, über den Sommer nach oben“   Ritchie sagte. „Im Laufe des Jahres, habe ich   Strukturen und wahrscheinlich machte die   Compiler Code etwas besser -   bessere Code - und so in dem nächsten   Sommer, war, dass, wenn wir das gemacht   Aufwand aufeinander abgestimmte und hat tatsächlich Redo   das ganze Betriebssystem in C. "


Hier ist ein perfektes Beispiel dafür, was ich meine. Aus den Kommentaren:

  

Pointers existieren nur das Schreiben eines Compilers einfacher zu machen? Nr Pointers existieren, weil sie die einfachste mögliche Abstraktion über die Idee Indirektionsebene sind. - Adam Rosenfield (eine Stunde vor)

Sie haben Recht. Um indi zu implementierenrection, Zeiger sind die einfachsten mögliche Abstraktion zu implementieren. In keiner Weise sind sie die einfachste Möglichkeit zu begreifen oder zu verwenden. Arrays sind viel einfacher.

Das Problem? Um Arrays implementieren so effizient wie Zeiger Sie müssen ziemlich einen riesigen Haufen von Code zu Ihrem Compiler hinzuzufügen.

Es gibt keinen Grund, warum sie nicht C ohne Zeiger ausgelegt sein können, aber mit Code wie folgt:

int i=0;
while(src[++i])
    dest[i]=src[i];

wird es viel Mühe nehmen (seitens Compiler) den expliziten i + src Faktor und i + dest Ergänzungen und es den gleichen Code machen zu schaffen, dass dies machen:

while(*(dest++) = *(src++))
    ;

Factoring, dass Variable „i“ nach der Tat hart ist. es war neu Compiler kann es tun, aber damals einfach nicht möglich, und das Betriebssystem auf dieser beschissenen Hardware benötigt wenig Optimierungen wie das ausgeführt wird.

Jetzt wenige Systeme benötigen diese Art von Optimierung (Ich arbeite an einen der langsamsten Plattformen um - Kabel-Set-Top-Boxen, und die meisten unserer Sachen sind in Java) und in dem seltenen Fall, dass Sie es brauchen könnten, die neue C-Compiler sollten intelligent genug sein, um diese Art der Umwandlung auf seiner eigenen zu machen.

Wenn Sie C ++ wollen ohne Header-Dateien, dann habe ich eine gute Nachricht für Sie.

Es ist bereits vorhanden und wird als D ( http://www.digitalmars.com/d/ index.html )

Technisch D scheinen viel schöner als C ++ zu sein, aber es ist einfach nicht Mainstream genug für den Einsatz in vielen Anwendungen im Moment.

Einer von C ++ 's Zielen ist eine Obermenge von C zu sein, und es ist schwierig, es so zu tun, wenn es nicht die Header-Dateien unterstützen. Und durch die Erweiterung, wenn Sie verbrauch Header-Dateien möchten, können Sie prüfen, wie gut CPP Exzision (die Pre-Prozessor, nicht Plus-Plus) zusammen; beide C # und Java nicht angeben Makro Pre-Prozessoren mit ihren Standards (aber es sollte in einigen Fällen festgestellt werden, die sie sein können und auch verwendet werden, auch mit diesen Sprachen).

Als C ++ jetzt entworfen ist, können Sie Prototypen müssen - genauso wie in C - statisch jeden kompilierten Code zu überprüfen, die externen Funktionen und Klassen verweist. Ohne Header-Dateien, würden Sie diese Klassendefinitionen und Funktionsdeklarationen vor der Verwendung von ihnen tippen müssen. Für C ++ nicht Header-Dateien zu verwenden, dann würden Sie hinzufügen müssen, um eine Funktion in der Sprache, die so etwas wie Java import Stichwort unterstützen würde. Das wäre eine wichtige Ergänzung und geändert werden; Antwort auf Ihre Frage, ob es sinnvoll sein würde: Ich glaube nicht - überhaupt nicht

.

Viele Menschen sind sich dessen bewusst Mängel der Header-Dateien und es gibt Ideen leistungsstärkere Modulsystem zu C ++ einzuführen. Vielleicht haben Sie einen Blick auf Module in C nehmen wollen ++ (Revision 5) von Daveed Vandevoorde.

Nun, C ++ per se nicht die Header-Dateien beseitigen, weil die Abwärtskompatibilität. Aber ich denke, dass sie eine dumme Idee im Allgemeinen sind. Wenn Sie eine Closed-Source-lib verteilen möchten, können diese Informationen automatisch extrahiert werden. Wenn Sie verstehen wollen, wie eine Klasse verwenden w / o bei der Umsetzung suchen, das ist, was Dokumentation Generatoren sind, und sie haben eine verdammt viel besser ein Job.

Es ist Wert bei der Definition der Klasse Schnittstelle in einer separaten Komponente der Implementierungsdatei.

Es kann mit Schnittstellen erfolgen, aber wenn Sie diesen Weg gehen, dann sagen Sie implizit, dass Klassen in Bezug auf einen Mangel Umsetzung von Vertrag zu trennen.

Modula 2 hatte die richtige Idee, Definition Module und Implementierungsmodule. http://www.modula2.org/reference/modules.php

Java / C # 's Antwort ist eine implizite Umsetzung der gleiche (wenn auch objektorientiert.)

Header-Dateien sind eine Flickschusterei, da die Header-Dateien Implementierung Detail äußern (wie private Variablen.)

Bei der Bewegung über Java und C #, finde ich, dass, wenn eine Sprache für die Entwicklung IDE-Unterstützung erfordert (so dass öffentliche Klasse Schnittstellen befahrbar ist in Klasse-Browser), dann ist dies vielleicht eine Erklärung, dass der Code nicht einge steht seine eigene Verdiensten als besonders lesbar zu sein.

Ich finde die Mischung aus Schnittstelle mit Implementierungsdetails ziemlich horrend.

Entscheidend ist, zeigt mir der Mangel an Fähigkeit, die öffentliche Klasse Signatur in einer prägnanten gut kommentierten Datei unabhängig von Implementierung zu dokumentieren, dass die Sprache Design für die Bequemlichkeit des Urhebers geschrieben, eher Bequemlichkeit der Wartung. Nun, ich bin weitläufig über Java und C # jetzt.

Ein Vorteil dieser Trennung ist, dass es einfach ist, nur die Schnittstelle zu sehen, ohne erfordert eine erweiterten Editor .

Wenn Sie den Grund wollen, warum dies nie passieren wird: es ziemlich alle vorhandenen C ++ Software brechen. Wenn Sie in einigen der Ausschuss Design-Dokumentation ++ C aussehen, sahen sie verschiedene Alternativen an, um zu sehen, wie viel Code, es würde brechen.

Es wäre viel einfacher, die Switch-Anweisung in etwas halbwegs intelligent zu verändern. Das wäre nur ein wenig Code brechen. Es ist immer noch nicht geschehen wird.

FOR NEW IDEA EDITED:

Der Unterschied zwischen C ++ und Java, die C ++ Header macht notwendige Dateien ist, dass C ++ Objekte sind nicht unbedingt Zeiger. In Java werden alle Klasseninstanzen bezeichnet durch den Zeiger, obwohl es nicht so aussieht. C ++ hat Objekte auf dem Heap zugewiesen und den Stapel. Das bedeutet, C ++ eine Möglichkeit zu wissen braucht, wie groß ein Objekt sein, und wo die Datenelemente sind im Speicher.

Keine Sprache existiert ohne Header-Dateien. Es ist ein Mythos.

Schauen Sie sich proprietäre Bibliothek Verteilung für Java (ich keine C # Erfahrung zu sprechen, aber ich würde erwarten, dass es das gleiche ist). Sie geben nicht die vollständige Quelldatei; sie geben Sie nur eine Datei mit jeder Implementierung der Methode ausgeblendet ({} oder {return null;} oder dergleichen), und alles, was sie mit Versteck versteckt weg erhalten können. Sie können nicht, dass alles andere als ein Kopf nennen.

Es gibt keinen technischen Grund jedoch, warum ein C oder C ++ Compiler alles in einer entsprechend markierten Datei als extern zählen konnte, es sei denn, dass Datei direkt kompiliert wird. Jedoch würden die Kosten für die Kompilierung sein immens, da weder C noch C ++ schnell zu analysieren, und das ist ein sehr wichtiger Aspekt. Alle komplexeren Verfahren von melding Kopf- und Quelle schnell technische Probleme wie die Notwendigkeit für den Compiler begegnen würden ein Objekt Layout zu kennen.

Header-Dateien sind ein integraler Bestandteil der Sprache. Ohne Header-Dateien, alle statischen Bibliotheken, dynamische Bibliotheken, so ziemlich jede vorkompilierte Bibliothek wird unbrauchbar. Header-Dateien es auch leichter machen, alles zu dokumentieren, und machen es möglich, eine Bibliothek / Datei-API zu überblicken, ohne jedes einzelne Bit der Code zu überschreiten.

Sie machen es auch einfacher, das Programm zu organisieren. Ja, müssen Sie ständig von der Quelle Umschalten Header, aber sie erlauben auch Sie interne und private APIs in den Implementierungen definieren. Zum Beispiel:

MySource.h:

extern int my_library_entry_point(int api_to_use, ...);

MySource.c:

int private_function_that_CANNOT_be_public();

int my_library_entry_point(int api_to_use, ...){
  // [...] Do stuff
}

int private_function_that_CANNOT_be_public() {

}

Wenn Sie #include <MySource.h> Sie dann my_library_entry_point erhalten.

Wenn Sie #include <MySource.c>, dann Sie auch erhalten private_function_that_CANNOT_be_public.

Sie sehen, wie das eine sehr schlechte Sache sein könnte, wenn Sie eine Funktion haben eine Liste von Passwörtern zu bekommen, oder eine Funktion, die Ihren Verschlüsselungsalgorithmus implementiert, oder eine Funktion, die die Interna eines O aussetzen würde, oder eine Funktion, die overrode Privilegien, etc.

Oh Ja!

Nach der Codierung in Java und C #, es ist wirklich ärgerlich, 2-Dateien für alle Klassen zu haben. Also ich dachte, wie kann ich sie zusammenführen, ohne vorhandenen Code zu brechen.

In der Tat, es ist wirklich einfach. Legen Sie einfach die Definition (Implementierung) innerhalb eines #ifdef Abschnitt und fügen Sie auf der Compiler-Befehlszeile ein definieren, um die Datei zu kompilieren. Das ist es.

Hier ist ein Beispiel:

/* File ClassA.cpp */

#ifndef _ClassA_
#define _ClassA_

#include "ClassB.cpp"
#include "InterfaceC.cpp"

class ClassA : public InterfaceC
{
public:
    ClassA(void);
    virtual ~ClassA(void);

    virtual void methodC();

private:
    ClassB b;
};

#endif

#ifdef compiling_ClassA

ClassA::ClassA(void)
{
}

ClassA::~ClassA(void)
{
}

void ClassA::methodC()
{
}

#endif

Auf der Befehlszeile kompiliert die Datei mit

-D compiling_ClassA

Die anderen Dateien, die KlasseA einschließen müssen nur tun können,

#include "ClassA.cpp"

Natürlich ist die Zugabe von der Definition auf der Kommandozeile leicht mit einer Makro-Erweiterung (Visual Studio-Compiler) oder mit einer automatischen Variablen (Gnu make) und unter Verwendung der gleiche Nomenklatur für die definieren Namen hinzugefügt werden kann.

Noch bekomme ich nicht den Punkt einiger Aussagen. Die Trennung von API und Implementierung ist eine sehr gute Sache, aber die Header-Dateien sind nicht API. Es gibt private Felder gibt. Wenn Sie ein privates Feld, das Sie ändern Implementierung hinzuzufügen oder zu entfernen und nicht die API.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top