33 votes

Pourquoi une fonction n'est-elle pas un objet?

J'ai lu dans les normes n4296 (Projet) § 1.8 page 7:

Un objet est une région de stockage. [ Note: Une fonction n'est pas un objet, indépendamment de si oui ou non il s'occupe de stockage dans la façon dont les objets ne. -la note de fin ]

J'ai passé quelques jours sur le net à la recherche d'une bonne raison pour une telle exclusion, avec pas de chance. Peut-être parce que je ne suis pas entièrement comprendre les objets. Donc:

  1. Pourquoi est une fonction et non un objet? Comment est-il différent?
  2. Et est ce que cela a un rapport avec les foncteurs (objets de fonction)?

43voto

Jerry Coffin Points 237758

Beaucoup de la différence vient de pointeurs et d'adressage. En C++1 pointeurs de fonctions et pointeurs vers les objets sont strictement séparées sortes de choses.

C++ nécessite que vous pouvez convertir un pointeur vers n'importe quel type d'objet dans un pointeur vers void, puis convertir le type d'original, et le résultat sera égal au pointeur vous avez commencé de 2. En d'autres termes, quel que soit exactement comment ils le font, la mise en œuvre doit s'assurer qu'une conversion de pointeur vers un objet de type de pointeur à vide est sans perte, donc, peu importe ce que l'original a été, toutes les informations contenues peuvent être recréé de sorte que vous pouvez récupérer le pointeur de même que vous avez commencé par conversion d' T* de void * et retour à l' T*.

C'est pas vrai avec un pointeur à une fonction si--si vous prenez un pointeur à une fonction, de les convertir en void *, puis de le convertir en un pointeur à une fonction, vous risquez de perdre certaines informations dans le processus. Vous pourriez ne pas récupérer le pointeur d'origine, et en référence à ce que vous obtenez de retour vous donne un comportement indéfini (en bref, de ne pas le faire).

Pour ce que ça vaut, vous pouvez, toutefois, de convertir un pointeur vers une fonction à un pointeur vers un autre type de fonction, puis de les convertir ce résultat en arrière à l'original, et vous avez la garantie que le résultat est le même que vous avez commencé avec.

Bien qu'il n'est pas particulièrement pertinent pour la discussion à la main, il y a quelques autres différences que peut être intéressant de noter. Par exemple, vous pouvez copier la plupart des objets, mais vous ne pouvez pas copier toutes les fonctions.

Autant que le lien avec la fonction des objets de passe: bien, il n'y a vraiment pas beaucoup d'un au-delà d'un point: un objet de fonction prend en charge la syntaxe qui ressemble à un appel de fonction-mais il est encore un objet, pas une fonction. Donc, un pointeur vers un objet de fonction est toujours un pointeur vers un objet. Si, par exemple, vous convertir de l'un à l' void *, puis convertir le type d'original, vous êtes toujours garanti que vous allez retrouver l'original de la valeur du pointeur (ce qui n'est pas vrai avec un pointeur à une fonction).

Quant à pourquoi les pointeurs de fonctions sont (au moins potentiellement) différent de pointeurs vers des objets: une partie revient à des systèmes existants. Par exemple, sur MS-DOS (entre autres), il y avait quatre entièrement distincte de modèles de mémoire: petite, moyenne, compact et grand. Petit modèle utilisé en 16 bits d'adressage, soit des fonctions ou des données. Utilisé comme moyen de 16 adresses de bits pour les données et de 20 adresses de bits pour le code. Compact renversé (16 adresses de bits pour le code, à 20 adresses de bits pour les données). Grand 20-adresses de bits pour le code et les données. Ainsi, dans le compact ou moyennes modèle, la conversion entre les pointeurs de code et des pointeurs vers des fonctions vraiment pu conduire à des problèmes.

Plus récemment, un certain nombre de Dsp ont utilisé entièrement distincte de la mémoire bus pour le code et pour les données et (comme avec MS-DOS modèles de mémoire), ils étaient souvent différentes largeurs, la conversion entre les deux pourrait et fait perdre de l'information.


  1. Ces règles sont entrées en C++ à partir de C, de sorte que le même est vrai dans C, pour tout ce qui en vaut la peine.
  2. Bien qu'il n'est pas directement nécessaire, avec la façon dont les choses fonctionnent, à peu près le même travaille à être vrai pour une conversion à partir du type d'original à un pointeur sur un char et à l'arrière, pour tout ce qui en vaut la peine.

5voto

pulp_fiction Points 10

Pourquoi une fonction n'est pas un objet? Comment est-il différent?

Pour comprendre cela, nous allons déplacer de bas en haut en termes d'abstractions impliqués. Donc, vous avez votre adresse espace à travers lequel vous pouvez définir l'état de la mémoire et nous devons nous rappeler que, fondamentalement, il est tout au sujet de cet état de fonctionnement sur.

Ok, nous allons passer un peu plus élevés en termes d'abstractions. Je ne suis pas prise au sujet de toutes les abstractions imposées par un langage de programmation encore (comme l'objet, tableau, etc.) mais tout simplement en tant que profane, je veux garder un enregistrement d'une partie de la mémoire, permet de l'appeler Ab1 et un autre appelé Ab2.

Les deux ont un état fondamentalement, mais j'ai l'intention de manipuler/faire usage de l'état différemment.

De la même façon...Pourquoi et Comment?

Pourquoi ?

En raison de mes exigences (pour effectuer une addition de 2 nombres et stocker le résultat en arrière, par exemple). Je serai d'utilisation) Ab1 comme un long usage de l'état et de l' Ab2 comme relativement courte de l'utilisation de l'état. Donc, je vais créer un état pour Ab1(avec les 2 nombres à ajouter), puis utiliser cet état pour remplir certains d'état d' Ab2(copier temporairement) et effectuer d'autres manipulations d' Ab2(ajouter) et sauver une partie de la résultante Ab2 de Ab1(la conséquence). Post qu' Ab2 devient inutile et nous réinitialisation de son état.

Comment?

Je vais avoir besoin de quelques de gestion de portions de garder une trace de ce que les mots à choisir à partir d' Ab1 et copie d' Ab2 et ainsi de suite. À ce stade, je me rends compte que je peux le faire fonctionner pour effectuer quelques opérations simples, mais quelque chose de grave, exigent une énoncés spécification de la gestion de cette mémoire.

Donc, je regarde pour de telles spécifications de gestion et il s'avère qu'il y existe une variété de ces spécifications (certains ayant intégré dans la mémoire de modèle, d'autres offrent de la flexibilité pour gérer la mémoire vous-même) avec un meilleur design. En fait, parce qu'ils(sans même de dicter la façon de gérer la mémoire directement) ont permis de définir l'encapsulation pour cette longue période de stockage et les règles de quand et comment cela peut être créée et détruite.

Il en va de même pour l' Ab2 mais la façon de les présenter, il me fait me sentir comme ce est très différente de l' Ab1. Et en effet, il s'avère être. Ils utilisent une pile pour la manipulation de l'état de l' Ab2 et de réserver de la mémoire de tas pour Ab1. Ab2 meurt après un certain temps.(après avoir fini de s'exécuter).

Aussi, la façon dont vous définissez quoi faire avec Ab2 se fait à travers encore une autre partie appelée Ab2_Code et de spécification Ab1 implique de même, Ab1_Code

Je dirais, c'est fantastique! Je reçois beaucoup de confort, ce qui me permet de résoudre beaucoup de problèmes.

Maintenant, je suis toujours à la recherche d'un profane, du point de vue donc je ne me sens pas vraiment surpris d'avoir passé par le processus de pensée de tout cela, mais si vous les choses en question de haut en bas, les choses peuvent devenir un peu difficile à mettre en perspective.(Je pense que c'est ce qui s'est passé dans votre cas)

BTW, j'ai oublié de mentionner qu' Ab1 est appelé un objet et officiellement Ab2 d'une pile de fonction alors qu' Ab1_Code est la définition de la classe et de l' Ab2_Code est la définition de la fonction de code.

Et c'est à cause de ces différences imposées par le PL, vous trouvez qu'ils sont tellement différents.(votre question)

Remarque: Ne prenez pas mon représentation de l' Ab1/Object comme un long stockage de l'abstraction comme une règle ou d'un béton chose - c'est du point de vue profane. Le langage de programmation fournit beaucoup plus de flexibilité en termes de gestion du cycle de vie d'un objet. Ainsi, un objet peut être déployé comme Ab1 , mais il peut être beaucoup plus.

Et est ce que cela a un rapport avec les foncteurs (objets de fonction)?

Notez que la première partie de réponse est valable pour de nombreux langages de programmation en général(y compris C++), cette partie a à voir spécifiquement avec C++ (dont les spec que vous avez cité). Vous avez donc le pointeur à une fonction, vous pouvez avoir un pointeur sur un objet trop. Juste une autre construction de programmation C++ définit. Notez que c'est pour avoir un pointeur à l' Ab1, Ab2 pour les manipuler plutôt que d'avoir un autre distincts abstraction pour agir.

Vous pouvez lire au sujet de sa définition, utilisation ici:

C++ Foncteurs et leurs utilisations

0voto

Muntasir Points 638

Permettez-moi de répondre à la question dans un langage plus simple (les termes).

Que fait une fonction contenir?

Il contient essentiellement des instructions pour faire quelque chose. Lors de l'exécution de ces instructions, la fonction peut stocker temporairement et / ou de l'utilisation des données - et peut renvoyer des données.

Bien que les instructions sont stockées quelque part - ces instructions ne sont pas considérées comme des objets.

Alors, quels sont les objets?

Généralement, les objets sont des entités qui contiennent des données - qui se manipulés / modifié / mis à jour par fonctions (les instructions).

Pourquoi la différence?

Parce que les ordinateurs sont conçus de manière à ce que les instructions ne dépend pas de données.

Pour comprendre cela, nous allons réfléchir sur une calculatrice. Nous n'différentes opérations mathématiques à l'aide d'une calculatrice. Dire, si nous voulons ajouter quelques chiffres, nous fournissons les nombres de la calculatrice. Peu importe ce que les chiffres sont, la calculatrice va ajouter de la même façon, en suivant les instructions (si le résultat est supérieur à la calculatrice de capacité de stockage, il affichera un message d'erreur, mais c'est à cause de la calculatrice de limitation pour stocker le résultat (les données), pas à cause de son mode d'ailleurs).

Les ordinateurs sont conçus de la même manière. C'est pourquoi, lorsque vous utilisez une fonction de la bibliothèque (par exemple, qsort()) sur certaines données qui sont compatibles avec la fonction, vous obtenez le même résultat que vous attendez - et la fonctionnalité de la fonction ne change pas si les modifications de données - parce que les instructions de la fonction reste inchangé.

Relation entre la fonction et les foncteurs

Les fonctions sont ensemble d'instructions; et tandis qu'ils sont en cours d'exécution, certaines données temporaires peuvent être requises pour le stockage. En d'autres termes, certains objets peuvent être temporairement créés lors de l'exécution de la fonction. Ces objets sont les foncteurs.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X