Doit C++ éliminer les fichiers d'en-tête?
De nombreux langages tels que Java, C#, ne pas séparer la déclaration de mise en œuvre. C# est un concept de classe partielle, mais la mise en œuvre et de la déclaration de toujours rester dans le même fichier.
Pourquoi ne pas le C++ ont le même modèle? Est-il plus pratique d'avoir des fichiers d'en-tête?
Je me réfère à des cours et à venir versions de C++ standard.
- Je crois que il n'y a pas de véritable raison pour les fichiers d'en-tête dans le C++. Toutes les informations stockées dans les est dupliquée dans la .rpc et peut être automatedly extrait (comme le montre l'www.lazycplusplus.com -- avertissement: havent utilisé). Le problème est la vitesse de compilation et C#&Java ont montré que cela soit insurmontable.
- L'affichage de ce qu'un commentaire comme je ne suis pas certain de mes informations 🙂 et je ne sais pas pourquoi c'est arriver a voté vers le bas et de la clôture. C'est une excellente question de l'OMI. 😉
- Comment www.lazycplusplus.com obtenez toutes les informations? Que faire si je voulais déclarer et de la réserve de vide pointeur dans le fichier d'en-tête pour une utilisation future? Il n'est jamais utilisé ou de référence dans le fichier cpp.
- Merci.... Je n'ai aucune idée pourquoi il a été voté trop
- Brian: tu veux dire quoi par "réserve un pointeur void"? Comme vous le savez probablement, de manière statique, les données allouées en C/C++ doit être défini manuellement dans le .rpc après avoir été déclarées dans l'en-tête (sauf si c'est un fichier dont l'étendue). Avec LazyC++, vous sautez simplement la tête de la déclaration et de l'écriture à la mise en œuvre-définition
- J'aimerais voir une meilleure solution que les fichiers d'en-tête, mais en raison de la compatibilité ascendante questions (qui se transforment souvent en arrière combatibility - gotta love comment le changement de classe privée membres de les sauts de l'ABI vous forçant à utiliser PIMPLs) je ne pense pas que nous avons un moins pire alternative... Upvoted.
- pas tous les renseignements sont dans le fichier cpp... si une méthode est virtuelle ou pas, c'est certainement pas dans le rpc. Relations de classe sont également pas partie de la rpc. La liste peut continuer, mais c'est suffisant pour réfuter l'allégation.
- Je veux "pad" la sizeof la classe réservant de place pour l'expansion future. C'est assez fréquent dans Win32 structures de voir un réservé variable qui n'est pas utilisé pour quoi que ce soit, je ne parle pas des membres statiques.
- Je vois maintenant que LazzC++ vous oblige à dupliquer beaucoup d'informations dans le fichier cpp. J'ai été vraiment question avec votre première déclaration que "Toutes les informations stockées dans les [fichiers d'en-tête] est reproduit dans le .rpc et peut être automatedly extrait" qui n'est tout simplement pas vrai.
- Tim, en effet. C'est pourquoi, dans LazyC++ vous pouvez définir tous les membres de la classe à l'intérieur de la définition de la classe. Par exemple, votre source .rpc (pas d'en-tête, vous n'en avez pas) comme: class Foo { public: void manger() { /*du code*/ } void sleep() { /*du code*/ } };
- Brian - voir ma réponse à Tim. Dans LazyC++ vous êtes en train d'écrire la définition de la classe (y compris tout rembourrage que vous voulez), vous ne sont tout simplement pas dupliquer les choses. Par ailleurs, votre "réserve" est un non-compatibles hack, vous êtes mieux avec le Chat du Cheshire idiome.
- Vous pouvez délibérément d'écrire le code de cette façon, cependant, même après l'exécution de LazyC++, il va générer deux fichiers et le fichier cpp ne contiennent pas toutes les informations dans le fichier d'en-tête. Des fonctions virtuelles est un bien meilleur exemple que mon "unused variable" exemple.
- Bien sûr, la rpc qui en résultent ne contiennent pas toutes les données présentes dans l'en-tête. Pourquoi ne vous vous souciez qu'bien? C'est juste un détail d'implémentation. Le point est que vous n'avez pas à vous inquiéter à ce sujet, le compilateur s'en occupe pour vous.
- Relisez votre premier commentaire. Il suggère que je peux extraire mes fichiers d'en-tête à partir de mes fichiers cpp qui est absurde. Je peux cependant d'abord de les combiner ensuite utiliser LazyC++ pour les extraire. LazyC++ vous oblige à combiner, mais ce n'est pas la preuve de votre "dupliquer l'information" réclamation.
- D'accord, je n'étais pas aussi clair que possible dans mon premier commentaire. Avec cela de la sorte, on peut peut-être revenir sur le sujet... que pensez-vous de l'OP question?
- Ouais désolé pour garder l'affichage ami, c'est clair que nous comprenons tous les deux. Je suis déchiré sur la question. Le maintien d'un fichier d'en-tête est souvent fastidieux, mais un seul géant fichier peut être difficile de naviguer. LazyC++ est un concept intéressant, mais je vais fuir, sauf si il a été pris en charge par mon IDE/fournisseur de compilateur.
Vous devez vous connecter pour publier un commentaire.
J'ai régulièrement flip entre C# et C++, et l'absence de fichiers d'en-tête dans le C# est une de mes plus grandes bêtes noires. Je peux regarder un fichier d'en-tête et d'apprendre tout ce que je besoin de savoir à propos d'une classe - ce que c'est les fonctions membres sont appelés, leur syntaxe d'appel, etc, sans avoir à parcourir les pages de ce code qui implémente la classe.
Et oui, je connais des classes partielles et #régions, mais ce n'est pas la même. Classes partielles en fait aggraver le problème, car la définition d'une classe est répartie sur plusieurs fichiers. Aussi loin que #régions vont, ils ne semblent jamais être élargi dans la manière que j'aimerais pour ce que je fais en ce moment, donc je dois passer du temps à l'expansion de ces peu plus, jusqu'à me rendre la vue.
Peut-être que si intellisense de Visual Studio a mieux fonctionné pour le C++, je n'aurais pas un motif impérieux d'avoir à le consulter .h fichiers si souvent, mais même dans VS2008, C++'s intellisense ne peut pas toucher de C#
Rétro-Compatibilité - fichiers d'en-Tête ne sont pas éliminés parce qu'il allait se casser la Compatibilité ascendante.
Fichiers d'en-tête indépendante de la compilation. Vous n'avez pas besoin d'accéder ou même la mise en œuvre des fichiers à compiler un fichier. Cela peut rendre plus facile distribué construit.
Cela permet également de Kits de développement logiciel pour faire un peu plus facile. Vous pouvez fournir uniquement les en-têtes et de certaines bibliothèques. Il y a, bien sûr, des façons de contourner ce qui en d'autres langues.
Même Bjarne Stroustrup a appelé les fichiers d'en-tête une bidouille.
Mais sans un standard format binaire qui contient les métadonnées (comme les fichiers de classe Java, ou .Net fichiers PE) je ne vois pas de toute façon de mettre en œuvre la fonctionnalité. Une dépouillé d'un ELFE ou d'un.binaire n'a pas beaucoup d'informations que vous auriez besoin de les extraire. Et je ne pense pas que l'information est stockée dans Windows XCOFF fichiers.
Dans La Conception et l'Évolution de C++, Stroustrup donne une raison de plus...
Le même fichier d'en-tête peut avoir deux ou plusieurs fichiers de mise en œuvre qui peuvent être simultanément travaillé sur plus d'un programmeur sans la nécessité d'une source-système de contrôle.
Cela peut paraître bizarre de ces jours, mais je suppose que c'est une question importante quand le C++ a été inventé.
#ifdef
-fu. (Il suffit d'utiliser un makefile qui génère le bonmyclass.o
à partir de la plate-forme dépendant demyclass-win.cpp
/myclass-linux.cpp
, et l'extérieur se soucie demyclass.h
)C a été fait pour rendre l'écriture d'un compilateur facilement. Il fait BEAUCOUP de choses basées sur ce principe. Les pointeurs n'existent que pour faire de l'écriture d'un compilateur plus facile, comme le font les fichiers d'en-tête. Beaucoup de choses reporté à C++ sont basés sur la compatibilité avec ces fonctionnalités mises en œuvre pour faire compilateur écrit plus facile.
C'est une bonne idée en fait. Quand C a été créé, C et Unix étaient une sorte de paire. C portage d'Unix, Unix couru C. De cette façon, C et Unix peut rapidement se propager à partir de la plate-forme alors qu'un OS basé sur l'assemblée a dû être complètement ré-écrit pour être porté.
Le concept de la spécification d'une interface dans un fichier, et la mise en œuvre dans un autre n'est pas une mauvaise idée du tout, mais ce n'est pas ce que C fichiers d'en-tête sont. Ils sont simplement un moyen de limiter le nombre de passes d'un compilateur a faire par l'intermédiaire de votre code source et de permettre à certains limité abstraction du contrat entre les fichiers afin qu'ils puissent communiquer.
Ces éléments, les pointeurs, fichiers d'en-tête, etc... n'offrent pas vraiment un avantage par rapport à un autre système. En mettant le plus d'efforts dans le compilateur, vous pouvez compiler un objet de référence, aussi facilement qu'un pointeur vers l'exact même code objet. C'est ce que le C++ ne l'est aujourd'hui.
C est un grand, un langage simple. Il avait un nombre très limité de fonctionnalités, et vous pourriez écrire un compilateur sans trop d'effort. Le portage est généralement trivial! Je ne suis pas en train de dire que c'est un mauvais langage ou rien, c'est juste que C principaux objectifs quand il a été créé peuvent laisser des fragments dans la langue qui sont plus ou moins inutiles maintenant, mais vont être conservés à des fins de compatibilité.
Il semble que certaines personnes ne crois pas vraiment que C était écrit à port Unix, donc ici: (à partir de)
Ici est un parfait exemple de ce que je veux dire. À partir des commentaires:
Vous avez raison. Afin de mettre en œuvre indirection, les pointeurs sont les plus simples possible d'abstraction à mettre en œuvre. En aucune manière sont-ils les plus simples possible afin de les comprendre ou de les utiliser. Les tableaux sont beaucoup plus facile.
Le problème? Pour mettre en œuvre des tableaux de manière aussi efficace que les pointeurs vous avez à peu près l'ajout d'un ÉNORME tas de code de votre compilateur.
Il n'y a pas de raison qu'ils ne pouvaient pas conçues C sans pointeurs, mais avec ce code:
il va prendre beaucoup d'efforts (sur les compilateurs partie) afin de tenir compte de manière explicite de la i+src et i+dest ajouts et de faire créer le même code que cela ferait:
D'affacturage que la variable "i" après la réalité est DIFFICILE. De nouveaux compilateurs peuvent le faire, mais à l'époque, il n'était tout simplement pas possible, et le système d'exploitation s'exécutant sur cette merde de matériel nécessaire peu d'optimisations comme ça.
Maintenant, peu de systèmes ont besoin de ce genre d'optimisation (je travaille sur l'un des plus faibles des plates-formes autour-de décodeurs câble, et la plupart de nos affaires est en Java) et dans les rares cas où vous pourriez avoir besoin d'elle, les nouveaux compilateurs C devrait être assez intelligent pour faire ce genre de conversion sur son propre.
Si vous voulez C++ sans fichiers d'en-tête, puis j'ai de bonnes nouvelles pour vous.
Il existe déjà et s'appelle D (http://www.digitalmars.com/d/index.html)
Techniquement D semble être beaucoup plus agréable que de C++, mais il n'est tout simplement pas assez mainstream pour une utilisation dans de nombreuses applications pour le moment.
Un de C++objectifs est d'être un sur-ensemble de C, et il est difficile pour elle de le faire si il ne peut pas soutenir fichiers d'en-tête. Et, par extension, si vous souhaitez d'accise fichiers d'en-tête vous pouvez envisager aussi bien l'excision du RPC (le pré-processeur, pas plus-plus) en tout; C# et Java ne spécifiez pas de macro pré-processeurs avec leurs normes (mais il convient de noter que dans certains cas ils peuvent être et sont même utilisées, même avec ces langues).
Que C++ est conçu droit maintenant, vous avez besoin de prototypes, un peu comme en C -- statiquement vérifier tout le code compilé que les références externes de fonctions et de classes. Sans les fichiers d'en-tête, vous devez taper ces définitions de classe et les déclarations de fonction avant de les utiliser. Pour le C++ de ne pas utiliser les fichiers d'en-tête, vous devez ajouter une fonction dans la langue qui serait en charge de quelque chose comme Java
import
mot-clé. Ce serait un ajout majeur, et de changement; pour répondre à votre question de savoir s'il serait pratique: je ne crois pas, pas du tout.Beaucoup de gens sont conscients des lacunes de fichiers d'en-tête et il y a des idées à introduire plus puissant système de modules en C++.
Vous voudrez peut-être jeter un oeil à Des Modules en C++ (Révision 5) par Daveed Vandevoorde.
Bien, C++ en soi ne devrait pas éliminer les fichiers d'en-tête en raison de la compatibilité. Cependant, je ne pense qu'ils ont une idée stupide en général. Si vous souhaitez distribuer un code source fermé lib, ces informations peuvent être extraites automatiquement. Si vous voulez comprendre comment utiliser une classe w/o à la recherche à la mise en œuvre, c'est ce que la documentation générateurs sont pour, et ils font un diable de beaucoup mieux un emploi.
Il ya une valeur dans la définition de la classe de l'interface dans une composante distincte de la mise en œuvre de fichier.
Il peut être fait avec les interfaces, mais si vous allez dans cette voie, alors vous êtes implicitement en disant que les classes sont déficientes en termes de séparer la mise en œuvre du contrat.
Modula 2 a eu la bonne idée, des modules de définition et de mise en œuvre des modules. http://www.modula2.org/reference/modules.php
Java/C#'s réponse est implicitement mise en œuvre de la même (quoique orienté objet.)
Fichiers d'en-tête sont une bidouille, parce que les fichiers d'en-tête express détail de l'implémentation (comme les variables privées.)
Dans le déplacement de plus de Java et C#, je trouve que si une langue requiert une IDE de soutien pour le développement (tels que la classe public interfaces sont navigables dans la catégorie des navigateurs), alors c'est peut-être une déclaration que le code ne pas se tenir debout sur ses propres mérites, comme étant particulièrement lisible.
Je trouve le mélange de l'interface avec la mise en œuvre détail tout à fait horrible.
Surtout, le manque de capacité de documenter le public de la classe de signature dans un concis bien commenté fichier indépendant de la mise en œuvre, m'indique que la conception de langage est écrit pour la commodité de l'auteur, plutôt commodité de l'entretien. Eh bien, je m'égare sur Java et C# maintenant.
Un avantage de cette séparation, c'est qu'il est facile d'afficher uniquement l'interface, sans nécessitant une avancé de l'éditeur.
Si vous voulez la raison pour laquelle cela ne se produira jamais: elle allait se briser à peu près tous C++ existant logiciel. Si vous regardez de près le comité C++ documentation de conception, ils ont examiné les différentes options pour voir comment beaucoup de code, il allait se briser.
Il serait beaucoup plus facile de modifier l'instruction switch en quelque chose à mi-chemin intelligent. Qui briserait seulement un peu de code. Il n'est pas encore va se passer.
ÉDITÉ POUR LA NOUVELLE IDÉE:
La différence entre C++ et Java qui fait de C++ fichiers d'en-tête nécessaire, c'est que les objets C++ ne sont pas nécessairement des pointeurs. En Java, toutes les instances de classe sont visés par pointeur, bien qu'elle n'en a pas l'air. C++ a des objets alloués sur le tas et la pile. Cela signifie, C++ doit avoir un moyen de savoir la taille d'un objet et où les membres de données sont en mémoire.
Aucune langue n'existe sans les fichiers d'en-tête. C'est un mythe.
De regarder n'importe quel propriétaire de la bibliothèque de la distribution de Java (je n'ai pas le C# de l'expérience à proprement parler, mais j'imagine que c'est la même chose). Ils ne vous donnent pas l'complet du fichier source; ils viennent de vous donner un fichier avec toutes les méthodes de mise en œuvre du vide (
{}
ou{return null;}
ou similaires) et tout ce qu'ils peuvent s'en tirer avec de cacher caché. Vous ne pouvez pas appeler que rien, mais un en-tête.Il n'y a pas de raison technique, cependant, pourquoi un C ou C++ compilateur a pu compter tout au bien-fichier marqué comme
extern
à moins que ce fichier est compilé directement. Cependant, les coûts de la compilation serait immense, parce que ni C ni C++ est rapide à analyser, et c'est une considération très importante. Plus complexe, la méthode de fusion des en-têtes et une source de rapidement rencontrer des problèmes techniques, comme la nécessité pour le compilateur pour connaître un objet de mise en page.Fichiers d'en-tête sont une partie intégrante de la langue. Sans les fichiers d'en-tête, toutes les bibliothèques statiques, dynamiques des bibliothèques, à peu près tous les pré-compilé bibliothèque devient inutile. Fichiers d'en-têtes facilitent tout document, et de le rendre possible pour regarder par-dessus une bibliothèque/fichier API, sans aller plus chaque bit du code.
Ils font également plus facile à organiser votre programme. Oui, il faut constamment être à la commutation de la source à la tête, mais ils vous permettent également de définir des internes et des Api privées à l'intérieur de la mise en œuvre. Par exemple:
Masource.h:
Masource.c:
Si vous
#include <MySource.h>
, puis vous obtenez desmy_library_entry_point
.Si vous
#include <MySource.c>
, alors vous aussi obtenirprivate_function_that_CANNOT_be_public
.Vous voir comment cela pourrait être une très mauvaise chose si vous aviez une fonction permettant d'obtenir une liste de mots de passe, ou une fonction de mise en œuvre de votre algorithme de chiffrement, ou une fonction qui permettrait d'exposer le fonctionnement interne d'un OS, ou une fonction qui l'emportaient sur les privilèges, etc.
Oh Oui!
Après le codage en Java et C# c'est vraiment ennuyeux d'avoir 2 fichiers pour toutes les classes. Donc, je pensais à comment puis-je les fusionner sans casser le code existant.
En fait, c'est vraiment facile. Il suffit de mettre la définition (mise en œuvre) à l'intérieur d'un #ifdef l'article et ajouter une définition sur la ligne de commande du compilateur pour compiler ce fichier. C'est tout.
Voici un exemple:
Sur la ligne de commande, de compiler ce fichier avec
Les autres fichiers doivent inclure des ClassA suffit de faire
Bien sûr l'ajout de la définir sur la ligne de commande peuvent facilement être ajoutées à l'aide d'une macro d'extension (compilateur Visual Studio) ou avec un système automatique de variables (gnu make) et en utilisant la même nomenclature pour la définir un nom.
Encore je ne comprends pas le point de certains états. La séparation de l'API et la mise en œuvre est une très bonne chose, mais les fichiers d'en-tête ne sont pas de l'API. Il y a des champs privés de là. Si vous ajoutez ou supprimez du domaine privé vous modifiez la mise en œuvre et non pas de l'API.