Question

Apparemment (au moins selon gcc -std=c99) C99 ne supporte pas la surcharge de fonction. La raison de ne pas soutenir une nouvelle fonctionnalité C est généralement une compatibilité ascendante, mais dans ce cas je ne peux pas penser à un seul cas où la surcharge de fonction casserait la compatibilité ascendante. Quel est le raisonnement derrière cette fonction ne comprenant pas de base?

Était-ce utile?

La solution

Pour comprendre pourquoi vous n'êtes pas susceptible de voir une surcharge en C, il pourrait aider à mieux apprendre la surcharge est gérée par C ++.

Après la compilation du code, mais avant qu'il ne soit prêt à fonctionner, l'intermédiaire code objet doivent être liés. Cela transforme une base de données brute des fonctions compilées et d'autres objets dans un prêt à charger / fichier binaire exécuter. Cette étape supplémentaire est importante car elle est le mécanisme principe de modularité disponible pour les programmes compilés. Cette étape vous permet de prendre le code des bibliothèques existantes et le mélanger avec votre propre logique de l'application.

A ce stade, le code objet peut avoir été écrit dans toutes les langues, avec une combinaison de caractéristiques. Pour que cela soit possible, il est nécessaire d'avoir une sorte de convention pour que l'éditeur de liens est en mesure de choisir l'objet à droite quand un autre objet fait référence. Si vous codez en langage assembleur, lorsque vous définissez une étiquette, cette étiquette est utilisée exactement, car on suppose que vous savez ce que vous faites.

En C, les fonctions deviennent les noms de symboles pour l'éditeur de liens, de sorte que lorsque vous écrivez

int main(int argc, char **argv) { return 1; }

le compilateur fournit une archive de code objet, qui contient un objet appelé main.

Cela fonctionne bien, mais cela signifie que vous ne pouvez pas avoir deux objets avec le même nom, parce que l'éditeur de liens serait incapable de décider quel nom il doit utiliser. L'éditeur de liens ne sait rien sur les types d'arguments, et très peu sur le code en général.

C ++ résout ce en codant des informations supplémentaires dans le nom du symbole directement. Le type de retour et le nombre et le type d'arguments sont ajoutés au nom du symbole, et sont appelés ainsi au point d'un appel de fonction. L'éditeur de liens ne pas savoir ce qui se passe même, étant donné que dans la mesure où il peut le dire, l'appel de fonction est sans ambiguïté.

L'inconvénient est que les noms de symboles ne regardent rien comme les noms de fonctions d'origine. En particulier, il est presque impossible de prédire ce que le nom d'une fonction surchargée sera pour vous permettre de créer un lien vers elle. Pour créer un lien vers le code Foriegn, vous pouvez utiliser extern "C", ce qui provoque ces fonctions à suivre le style C des noms de symboles, mais bien sûr vous ne pouvez pas surcharger une telle fonction.

Ces différences sont liées aux objectifs de conception de chaque langue. C est orientée vers la portabilité et l'interopérabilité. C va de sa façon de faire les choses prévisibles et compatibles. C ++ est plus fortement orientée vers la construction de systèmes riches et puissants, et pas très concentré sur l'interaction avec d'autres langues.

Je pense qu'il est peu probable que C à jamais poursuivre une fonctionnalité qui produirait un code qui est aussi difficile d'interagir avec en C ++.

Modifier : Imagist demande:

  

Serait-il vraiment moins portable ou   plus difficile d'interagir avec   fonction si vous int résolu principal (int   argc, char ** argv) à quelque chose comme   main-int-int-char ** au lieu de principal   (Et cela faisait partie de la norme)?   Je ne vois pas de problème ici. En réalité,   il me semble que cela vous donne   plus d'informations (qui pourrait être utilisé   pour l'optimisation, etc.)

Pour répondre à cela, je ramènerai à C ++ et la façon dont il traite les surcharges. C ++ utilise ce mécanisme, presque exactement comme décrit, mais avec une mise en garde. C ++ ne normalise pas comment certaines parties de lui-même devraient être mises en œuvre, et continue de suggérer comment quelques-unes des conséquences de cette omission. En particulier, C ++ possède un riche système de type, qui comprend des membres de la classe virtuelle. Comment cette fonction doit être mise en œuvre est laissée aux auteurs du compilateur, et les détails de la résolution vtable a un effet important sur les signatures de fonction. Pour cette raison, C ++ suggère délibérément les auteurs du compilateur font mutiler nom incompatibles entre elles dans comPilers ou même compilateurs avec différentes implémentations de ces principales caractéristiques.

Ceci est juste un symptôme de la question plus profonde que tandis que les langues de niveau supérieur comme C ++ et C ont des systèmes de type détaillés, le code de la machine de niveau inférieur est totalement sans type. les systèmes de type arbitraire riches sont construits au-dessus du binaire typées fourni au niveau de la machine. Linkers n'ont pas accès aux riches informations de type disponible pour les langues de niveau supérieur. L'éditeur de liens est complètement dépendant du compilateur de traiter toutes les abstractions de type et produire du code objet libre de type-correctement.

C ++ le fait en codant toutes les informations de type nécessaire dans les noms des objets déchiquetés. C, cependant, a une portée sensiblement différente, dans le but d'être une sorte de langage assembleur portable. C préfère donc avoir une stricte à une correspondance entre le nom déclaré et le nom du symbole objets résultant. Si C mutilée il est des noms, même d'une manière standardisée et prévisible, vous devez aller à de grands efforts pour faire correspondre les noms modifiés aux noms de symbole de votre choix, ou bien vous devrez désactiver comme vous le faites en c ++. Cet effort supplémentaire est presque aucun avantage, parce que contrairement à C ++, système de type C de est assez petit et simple.

En même temps, il est pratiquement une pratique standard pour définir plusieurs fonctions C nommées de la même qui ne varient que par les types qu'ils prennent comme arguments. pour un exemple long de tout cela, un coup d'oeil à la espace de noms OpenGL.

Autres conseils

Lorsque vous compilez une source C, les noms de symboles restent intacts. Si vous introduisez la surcharge de fonctions, vous devez fournir une technique mutiler nom pour éviter les conflits de noms. Par conséquent, comme C ++, vous aurez la machine généré des noms de symboles dans le binaire compilé.

En outre, C ne dispose pas de typage strict. Beaucoup de choses sont implicitement convertibles les uns aux autres en C. La complexité des règles de résolution de surcharge pourrait introduire la confusion dans ce genre de langage.

Beaucoup de créateurs de langue, y compris moi, pensent que la combinaison de surcharge de fonction des promotions implicites C peut produire un code qui est odieusement difficile à comprendre. Pour preuve, regardez l'ensemble des connaissances accumulées sur C ++.

En général, C99 était destinée à être une modeste révision largement compatible avec la pratique existante. Surcharge aurait été un départ assez grand.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top