Pourquoi le langage C n'est-il pas considéré comme un langage «orienté objet»?

92

Il semble que C ait ses propres quasi-objets, tels que des «structures», qui peuvent être considérés comme des objets (de la manière générale que nous pensons normalement).

Et aussi, les fichiers C eux-mêmes sont fondamentalement des "modules" séparés, non? Alors les modules ne sont-ils pas un peu comme des «objets» aussi? Je ne comprends pas pourquoi C, qui semble si semblable au C ++, est considéré comme un langage "procédural" de bas niveau où C ++ est un "orienté objet" de haut niveau.

* edit: (clarification) pourquoi et où, la ligne est-elle dessinée, qu'est-ce qu'un "objet" et ne l'est-il pas?

Templier noir
la source
40
Tous - pourquoi les votes négatifs? C'est une question basique mais pas mauvaise.
Jon Hopkins
7
Vous pouvez utiliser efficacement les principes OO en C (comme le font généralement les personnes qui écrivent du bon code C), mais le langage n’est pas conçu pour faciliter les choses, mais beaucoup plus récentes.
Asveikau
5
C a simplement une approche différente, plus simple et (pour être honnête) mieux définie (au moins parmi la communauté open-source) de l’abstraction des données. C ++ a tendance à être un puissant moteur d’abstraction et permet de nombreuses choses intéressantes, mais il faut supporter le coût de devoir comprendre comment [ne pas] les utiliser correctement, ce qui manque le plus souvent dans les programmes courants. Voir ma réponse complète pour plus de détails.
Yam Marcovic
1
En bref: les structures ne peuvent pas avoir de méthodes. (Le pointeur sur une fonction ne la coupe pas tout à fait).
SF.
1
Il est possible de faire de la programmation en C en utilisant des objets, avec quelques difficultés. Mais cela ne le rend pas orienté objet .
Wedge

Réponses:

101

Il semble que C ait ses propres quasi-objets tels que 'structs' qui peuvent être considérés comme des objets

Ensemble, parcourons la page Wikipedia sur la programmation orientée objet et cochez les caractéristiques des structures de style C qui correspondent à ce que l'on considère traditionnellement comme étant du style orienté objet:

(OOP) est un paradigme de programmation utilisant des "objets" - structures de données composées de champs de données et de méthodes associées à leurs interactions

Les structures C sont-elles constituées de champs et de méthodes ainsi que de leurs interactions ? Non.

Les techniques de programmation peuvent inclure des fonctionnalités telles que l’abstraction de données, l’encapsulation, la messagerie, la modularité, le polymorphisme et l’héritage.

Est-ce que les structures C font l'une de ces choses en "première classe"? Non, le langage vous oppose à chaque étape.

l'approche orientée objet encourage le programmeur à placer des données là où elles ne sont pas directement accessibles par le reste du programme

Est-ce que les structures C font cela? Non.

Un programme orienté objet contient généralement différents types d’objets, chaque type correspondant à un type particulier de données complexes à gérer ou éventuellement à un objet ou à un concept du monde réel.

Est-ce que les structures C font cela? Oui.

Les objets peuvent être considérés comme encapsulant leurs données dans un ensemble de fonctions conçues pour garantir que les données sont utilisées correctement

Non.

chaque objet est capable de recevoir des messages, de traiter des données et d'envoyer des messages à d'autres objets

Une structure peut-elle envoyer et recevoir des messages? Peut-il traiter des données? Non.

Les structures de données OOP ont tendance à "transporter leurs propres opérateurs"

Est-ce que cela se passe en C? Non.

Envoi dynamique ... Encapsulation ... Polymorphisme de sous-type ... Héritage d'objet ... Récursion ouverte ... Classes d'objets ... Instances de classes ... Méthodes agissant sur les objets attachés ... Message en cours de transfert .. Abstraction

Existe-t-il certaines de ces caractéristiques des structures C? Non.

Quelles caractéristiques des structures pensez-vous être "orientées objet"? Parce que je ne trouve personne d' autre que le fait que les structures définissent les types .

Maintenant, bien sûr, vous pouvez créer des structures avec des champs qui sont des pointeurs vers des fonctions. Vous pouvez faire en sorte que les structures aient des champs qui pointent vers des tableaux de pointeurs de fonction, correspondant aux tables de méthodes virtuelles. Etc. Vous pouvez bien sûr émuler C ++ en C, mais c’est une façon très peu idiomatique de programmer en C; vous feriez mieux d'utiliser simplement C ++.

Et aussi, les fichiers C eux-mêmes sont fondamentalement des "modules" séparés, non? Alors les modules ne sont-ils pas un peu comme des «objets» aussi?

Encore une fois, à quelles caractéristiques des modules pensez-vous qui les fait agir comme des objets? Les modules prennent-ils en charge l'abstraction, l'encapsulation, la messagerie, la modularité, le polymorphisme et l'héritage?

L'abstraction et l'encapsulation sont assez faibles. Évidemment les modules sont modulaires; c'est pourquoi ils s'appellent des modules. Messagerie? Ce n'est que dans le sens où un appel de méthode est un message et que les modules peuvent contenir des méthodes. Polymorphisme? Nan. Héritage? Nan. Les modules sont des candidats assez faibles pour les "objets".

Eric Lippert
la source
15
Je ne suis pas d'accord pour dire que "émuler C ++" (votre terme) n'est pas idiomatique. Un exemple de compteur serait la façon dont un noyau d'OS implémente généralement les opérations sur les fichiers - prenez Linux comme exemple, où vous avez des structures pleines de pointeurs de fonctions. Ce sont peut-être des idiomes quelque peu "spécifiques à un domaine" (limités à l’écriture de pilotes sur * nix, par exemple), mais ils sont reconnaissables et s’acquittent assez bien du travail à certaines fins. Il existe également quelques exemples de bibliothèques en mode utilisateur qui maîtrisent assez bien la notion d’OA; prenez Gtk + et les bibliothèques dont il dépend. Appelez-le hacky et vous aurez peut-être raison, mais ce n'est pas terrible de travailler avec
asveikau
5
@asveikau: L'idée qu'une pratique est inhabituelle (même si ce n'est pas du jamais vu) et "hacky" signifie-t-elle qu'elle n'est, par définition, pas idiomatique?
Adam Robinson
19
@asveikau: Bien sûr, il y a des choses que vous pouvez faire pour rendre les programmes C plus OO en style. Mais comme vous le dites, il faut de la discipline pour le faire. les fonctionnalités du langage elles-mêmes ne vous mènent pas naturellement vers l'encapsulation, le polymorphisme, l'héritage de classe, etc. Au lieu de cela, le développeur peut imposer ce modèle au langage. Cela ne signifie pas que les structures sont logiquement la même chose que les objets. Heck, vous pouvez aussi programmer dans un style OO dans Lisp, mais cela ne veut pas dire que les cellules sont des objets.
Eric Lippert
3
@asveikau, puis-je suggérer que votre interprétation (erronée) de "idiome" comme "propre" soit légèrement ... idiosyncratique? :)
Benjol
8
@ BillK: Les structures ne peuvent pas contenir de code en C. Les structures peuvent contenir des pointeurs de fonction , qui sont des données . Les pointeurs de fonction ne sont pas du code . Le code est un artefact textuel créé par un programmeur.
Eric Lippert
46

Le mot clé est "orienté", pas "objet". Même le code C ++ qui utilise des objets mais les utilise comme des structures n'est pas orienté objet .

C et C ++ peuvent faire de la programmation orientée objet (à l'exception de l'absence de contrôle d'accès en C), mais la syntaxe pour le faire en C est peu pratique (pour le moins qu'on puisse dire), tandis que la syntaxe en C ++ le rend très invitant. C est orienté vers la procédure, alors que C ++ est orienté vers les objets, malgré des capacités de base presque identiques à cet égard.

Le code qui utilise des objets pour implémenter des conceptions qui ne peuvent être créées qu'avec des objets (ce qui signifie généralement tirer parti du polymorphisme) est un code orienté objet. Le code qui utilise des objets ne représente guère plus que des poches de données, même en utilisant l'héritage dans un langage orienté objet, n'est en réalité qu'un code procédural plus compliqué qu'il ne le devrait. Le code en C qui utilise des pointeurs de fonction qui sont modifiés au moment de l’exécution avec des structures remplies de données est un peu en train de faire du polymorphisme, et pourrait être considéré comme étant "orienté objet", même dans un langage orienté procédure.

Kylben
la source
2
+1 Pour pointer notre C peut être OO. Ce n'est pas pratique, mais cela peut être fait.
dietbuddha
Il est plus facile de créer des objets dans VBA, mais je ne le considérerais pas non plus comme "orienté".
JeffO
J'appelle VBA "à base d'objet". Il utilise des objets, mais pas polymorphiquement, et dans le peu de travail que j'ai effectué, je ne suis pas sûr que vous puissiez même faire du polymorphisme, peu importe le type de code acrobatique que vous essayez. C'est essentiellement un langage procédural avec encapsulation.
Kylben
2
La plupart des langues peuvent agir en tant que langage OO, fonctionnel ou à peu près n'importe quel style de langage. la différence est le "Orienté" et je ne l'avais jamais entendu dire cela auparavant. J'aimerais pouvoir voter 3 fois dessus et l'accepter, c'est la bonne réponse.
Bill K
1
@kylben Il ne serait pas exagéré de stocker du code SQL dans la table, puis de l'extraire et de l'exécuter (en faisant de la table votre objet). Ce serait une expérience intéressante. En fait, c'est un peu tentant ...
Bill K
19

Basé sur les directeurs de très haut niveau:

Un objet est une encapsulation de données et de comportements liés entre eux, de sorte qu'ils fonctionnent dans leur ensemble, pouvant être instanciés plusieurs fois et traités comme une boîte noire si vous connaissez l'interface externe.

Les structures contiennent des données mais pas de comportement et ne peuvent donc pas être considérées comme des objets.

Les modules contiennent à la fois le comportement et les données mais ne sont pas encapsulés de manière à ce qu'ils soient liés et ne puissent certainement pas être instanciés plusieurs fois.

Et c'est avant que vous abordiez l'héritage et le polymorphisme ...

Jon Hopkins
la source
Comment se fait-il que comportement et données dans les modules ne soient pas liés? Les fonctions membres ne sont-elles pas fondamentalement le «comportement» des données présentes dans le module?
Dark Templar
4
Le problème est qu'ils ne sont pas encapsulés, pas qu'ils ne sont pas liés.
Eoin Carroll
En réalité, les objets sont principalement centrés sur le comportement et non sur les données. Data est / devrait être un citoyen de seconde classe en POO. Au lieu de cela, les structures sont centrées sur les données et n’ont aucun comportement.
Sklivvz
1
@Dark Templar - Ce que Eoin a dit ... C'est dans la nature de la relation. Je peux voir où vous venez - vous pourriez certainement utiliser Structs dans un module de telle manière qu'il émulé certains éléments très très basique de OO , mais une grande partie de ce que vous feriez reposerait sur le programmeur de coller à un ensemble de règles auto-imposées plutôt que d'avoir le langage l'appliquer. Et pourquoi vous déranger? Vous n'obtenez aucun des avantages de OO - pas d'héritage par exemple - et vous vous limitez.
Jon Hopkins
C'est une meilleure réponse que celle marquée correcte.
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
6

"structs" sont uniquement des données. Le test habituel rapide et erroné de l '"orientation d'objet" est le suivant: "Existe-t-il une structure permettant d'encapsuler le code et les données comme une seule unité?". C échoue, et est donc procédural. C ++ réussit ce test.

Brian Knoblauch
la source
6
Il existe des solutions de contournement, les structures peuvent avoir des pointeurs de fonction statiques vers les fonctions membres. Ils auront besoin d'un thispointeur explicite , mais dans ce cas, les données et les moyens de traitement des données seront encapsulés dans la structure.
Codeur
@ Brian Knoblauch: mais un fichier C n'est-il pas en soi une encapsulation de données et de code ??
Dark Templar
@DarkTemplar En un sens, oui, mais si vous parvenez à créer des unités de traduction, à les compiler et à les charger dans le processus en cours d'exécution au moment de l'exécution, cela ne vous servira à rien.
unités de traduction? >. <
Dark Templar
@Dark Templiers: une unité de traduction est un fichier source , plus rien #included en elle, et rien moins éliminé par pas conditionnel inclus ( #if, #ifdef, et analogues).
David Thornley
5

Le C, tout comme le C ++, a la capacité de fournir l’ abstraction de données , qui est un des idiomes du paradigme de programmation orientée objet qui existait avant lui.

  • Les structures C peuvent avoir des données (et c'est leur objectif principal)
  • Les structures C peuvent également définir des pointeurs de fonction en tant que données
  • Les structures C peuvent souvent être associées à un ensemble de fonctions, tout comme les méthodes. Seul le pointeur this n'est pas implicitement transmis, mais vous devez le spécifier explicitement comme premier argument de chaque méthode conçue pour gérer la structure spécifiée. C ++ le fait automatiquement pour vous, à la fois lorsque vous définissez et appelez des méthodes class / struct.

OOP en C ++ étend les moyens d'abstraction des données. Certains disent que c'est nocif , alors que d'autres le considèrent comme un bon outil lorsqu'il est utilisé correctement.

  • C ++ rend le pointeur this implicite en ne demandant pas à l'utilisateur de le passer à des "méthodes de la classe / struct" tant que le type peut être (au moins en partie) identifié.
  • C ++ vous permet de restreindre l'accès à certaines méthodes (fonctions de classe), et permet donc une programmation plus "défensive" ou "à l'abri des idiots".
  • C ++ encourage les abstractions en renforçant la sécurité de type en introduisant
    1. Le nouvel opérateur à la place de malloc + cast
    2. Modèles au lieu de pointeurs vides
    3. Fonctions en ligne recevant des valeurs typées au lieu de macros
    4. Polymorphisme intégré, que vous n'avez pas à implémenter vous-même, qui vous permet de créer des hiérarchies d'abstraction , des contrats et des spécialisations .

Cependant, vous trouverez de nombreux "hackers" de C qui prêchent que C est parfaitement capable d'abstraction et que les frais généraux créés par C ++ les empêchent seulement de résoudre le problème.

Modèles de programmation abstraits inefficaces dans lesquels, deux ans plus tard, vous remarquerez qu'une abstraction n'était pas très efficace, mais maintenant tout votre code dépend de tous les modèles d'objet sympas qui l'entourent, et vous ne pouvez pas le réparer sans réécrire votre application. -- Linus Torvalds

D'autres ont tendance à le considérer de manière plus équilibrée, acceptant à la fois les avantages et les inconvénients.

C, il est facile de se tirer dans le pied; Le C ++ rend la tâche plus difficile, mais lorsque vous le faites, votre jambe entière est balayée. - Bjarne Stroustrup

Yam Marcovic
la source
2

Vous devez regarder de l'autre côté de la médaille: C ++.

En POO, nous pensons à un objet abstrait (et concevons le programme en conséquence), par exemple une voiture capable de s’arrêter, d’accélérer, de tourner à gauche ou à droite, etc. Une structure avec un ensemble de fonctions ne correspond tout simplement pas au concept.

Avec les "vrais" objets, nous devons par exemple masquer les membres, ou nous pouvons aussi avoir un héritage avec une relation "est une" et bien plus encore.

APRÈS AVOIR LU LES COMMENTAIRES CI-DESSOUS: Il est vrai que tout (ou presque) peut être fait avec C (c'est toujours vrai), mais à première vue, j'ai pensé que ce qui sépare c de c ++ est la façon dont vous pensez lors de la conception d'un programme.

La seule chose qui fait vraiment la différence est l'imposition de politiques par le compilateur . c'est-à-dire une fonction virtuelle pure, etc. mais cette réponse ne concernera que des problèmes techniques, mais je pense que la principale différence (comme mentionné) est la façon dont vous pensez en codant, car C ++ vous donne une meilleure syntaxe intégrée pour faire de telles choses, au lieu de faire de la POO un peu maladroit en C.

Guy L
la source
Vous ne savez pas vraiment pourquoi une structure avec un "ensemble de fonctions" ne correspond pas au concept? +1 pour la réponse cependant
Dark Templar
1
À part le contrôle d'accès (privé / protégé / public), tout le reste peut être fait avec des structures.
Codeur
1
@DarkTemplar: Eh bien, vous pouvez essayer d'émuler la POO en C (les gens ont en fait écrit des ebooks sur ce sujet et le faire dans le monde réel, bien que très rarement), comme vous pouvez essayer d'émuler une programmation fonctionnelle en Java. Mais C ne fournit aucune aide, donc le langage C n'est pas orienté objet .
1

Vous l'avez en quelque sorte dit vous-même. Bien que C ait des objets qui sont un peu comme des objets, ils ne sont toujours pas des objets et c’est pourquoi C n’est pas considéré comme un langage POO.

Ryanzec
la source
1
Eh bien, je suppose que la question est la suivante: pourquoi et où la ligne de démarcation entre ce qui est un objet et ce qui ne l’est pas?
Dark Templar
1

Orienté objet fait référence à la fois à un motif architectural (ou même à un méta-motif) et aux langages dotés de fonctionnalités permettant de mettre en œuvre ou de rendre obligatoire l'utilisation de ce motif.

Vous pouvez implémenter un design "OO" (le bureau Gnome est peut-être le meilleur exemple de OO réalisé en C pur), j'ai même vu cela se réaliser avec COBOL!

Cependant, être capable de mettre en œuvre une conception OO ne rend pas le langage OO. Les puristes diraient que Java et C ++ ne sont pas vraiment des objets OO, car vous ne pouvez pas remplacer ou hériter des "types" de base tels que "int" et "char", et Java ne prend pas en charge l'héritage multiple. Mais comme ce sont les langages OO les plus utilisés et supportent la plupart des paradigmes, les programmeurs les plus "réels" qui sont payés pour produire du code fonctionnel les considèrent comme les langages OO.

C, d’autre part, ne supporte que les structures (comme le font COBOL, Pascal et des dizaines d’autres langages procéduraux), vous pouvez soutenir qu’il prend en charge l’héritage multiple en ce sens que vous pouvez utiliser n’importe quelle fonction sur n’importe quel élément de données, mais la plupart le considèrent comme un bogue. qu'une fonctionnalité.

James Anderson
la source
0

Regardons simplement la définition de OO:

  • Messagerie
  • Encapsulation
  • Reliure tardive

C ne fournit aucune de ces trois. En particulier, il ne fournit pas la messagerie , qui est la plus importante.

Jörg W Mittag
la source
1
Je pense que je devrais être en désaccord avec cela. Vous pouvez très certainement utiliser la messagerie en C - travailler avec les API Objective C à partir de C - et le découvrir en profondeur - et une liaison tardive peut être effectuée via des pointeurs de fonction, mais vous n’avez pas besoin de beaucoup de sucre syntaxique pour le masquer. (L'encapsulation est en fait facile en langage C; les pointeurs sur des types de structure incomplets fonctionnent parfaitement.)
Donal Fellows
L'héritage est également considéré comme important dans OO, et C ne le fait pas. L'élément le plus proche de l'encapsulation en C est constitué de fichiers distincts pouvant avoir des staticfonctions internal ( ) et des membres de données.
David Thornley
@DonalFellows, le message en train de passer en Objective-C pourrait facilement être implémenté en tant que macro C99. Le compilateur ne peut que tirer profit de la génération statique de toutes les structures nécessaires à partir de quelques lignes de code de haut niveau. La plupart, sinon toutes les fonctionnalités sont disponibles à partir de l'API C.
qpr
0

Il existe un certain nombre d'ingrédients clés pour OO, mais les plus importants sont que la majorité du code ne sait pas ce qu'il y a à l'intérieur d'un objet (ils voient l'interface de surface, pas l'implémentation), que l'état d'un objet est une unité gérée. (c.-à-d. lorsque l'objet cesse d'être ainsi que son état), et lorsqu'un code appelle une opération sur un objet, il le fait sans savoir exactement ce que l'opération est ou implique (tout ce qu'il fait est de suivre un modèle pour “Message” sur le mur).

C fait très bien l’encapsulation; Un code qui ne voit pas la définition d'une structure ne peut pas (légitimement) jeter un coup d'œil à l'intérieur. Tout ce que vous avez à faire est de placer une définition comme celle-ci dans un fichier d’en-tête:

struct FooImpl;
typedef struct FooImpl *Foo;

Bien sûr, il faudra une fonction qui construit Foos (c’est-à-dire une usine) et qui devrait déléguer une partie du travail à l’objet alloué lui-même (c’est-à-dire, par le biais d’une méthode «constructeur»), ainsi qu’un chemin de disposer de l'objet à nouveau (en le laissant nettoyer via sa méthode "destructor") mais c'est des détails.

L'envoi de méthode (c.-à-d. La messagerie) peut également s'effectuer par la convention selon laquelle le premier élément de la structure est en fait un pointeur sur une structure contenant des pointeurs de fonction et que chacun de ces pointeurs de fonction doit prendre un Foopremier argument. La répartition consiste alors à rechercher la fonction et à l'appeler avec le bon argument, ce qui n'est pas si difficile à faire avec une macro et un peu de ruse. (Cette table de fonctions constitue le cœur d'une classe dans un langage tel que C ++.)

En outre, cela vous donne également une liaison tardive: tout ce que le code de répartition sait, c’est qu’il appelle un décalage particulier dans une table pointée par l’objet. Cela ne doit être défini que lors de l'affectation et de l'initialisation de l'objet. Il est possible d’utiliser des systèmes d’envoi encore plus complexes qui vous apportent plus de dynamisme d’exécution (à un coût élevé en termes de rapidité), mais ils sont au-dessus du mécanisme de base.

Pourtant, cela ne signifie pas que C est un langage OO. La clé est que C vous laisse faire tout le travail difficile d’écrire les conventions et le mécanisme d’envoi vous-même (ou d’utiliser une bibliothèque tierce). C'est beaucoup de travail. De plus, cela ne fournit pas de support syntaxique ou sémantique, donc implémenter un système de classes complet (avec des éléments comme l'héritage) serait inutilement douloureux; Si vous avez affaire à un problème complexe bien décrit par un modèle orienté objet, un langage orienté objet sera très utile pour la rédaction de la solution. La complexité supplémentaire peut être justifiée.

Donal Fellows
la source
0

Je pense que C est parfaitement correct et décent pour la mise en œuvre de concepts orientés objet, haussement d'épaules . La plupart des différences que je vois entre le sous-ensemble de dénominateurs communs de langages considérés comme orientés objet sont mineures et de nature syntaxique, de mon point de vue pragmatique.

Commençons par, disons, la dissimulation d'informations. En C, nous pouvons y parvenir simplement en cachant la définition d’une structure et en l’utilisant avec des pointeurs opaques. Que efficacement les modèles de la publiccontre privatedistinction des champs de données que nous obtenons des classes. Et il est assez facile à faire et à peine anti-idiomatique, car la bibliothèque C standard repose énormément sur cela pour dissimuler des informations.

Bien sûr, vous perdez la possibilité de contrôler facilement où la structure est allouée en mémoire en utilisant des types opaques, mais ce n'est qu'une différence notable entre, par exemple, C et C ++. Le C ++ est certainement un outil supérieur pour comparer sa capacité à programmer des concepts orientés objet sur C tout en maintenant le contrôle sur les dispositions de mémoire, mais cela ne signifie pas nécessairement que Java ou C # est supérieur à C à cet égard, car ces deux perdre complètement la capacité de contrôler où les objets sont alloués en mémoire.

Et nous devons utiliser une syntaxe similaire fopen(file, ...); fclose(file);à opposée à file.open(...); file.close();mais big whoop. Qui se soucie vraiment? Peut-être juste quelqu'un qui mise beaucoup sur l'auto-complétion dans son IDE. Je reconnais que cela peut être une fonctionnalité très utile d’un point de vue pratique, mais peut-être pas une qui nécessite une discussion sur le point de savoir si une langue est adaptée à la programmation orientée objet.

Nous n'avons pas la capacité de mettre en œuvre efficacement les protectedchamps. Je vais totalement soumettre là. Mais je ne pense pas qu'il y ait de règle concrète qui dit: " Tous les langages OO devraient avoir une fonctionnalité permettant aux sous-classes d'accéder aux membres d'une classe de base auxquels les clients normaux ne devraient toujours pas accéder ." En outre, je vois rarement des cas d'utilisation pour des membres protégés qui ne craignent pas au moins de devenir un obstacle à la maintenance.

Et bien sûr, nous devons "émuler" le polymorphisme OO avec des tables de pointeurs de fonction et des pointeurs vers ceux-ci pour un envoi dynamique avec un peu plus de passe-partout pour initialiser ces analogiques vtableset vptrs, mais un peu de passe-passe ne m'a jamais causé beaucoup de chagrin.

L'héritage est à peu près la même chose. Nous pouvons facilement modéliser cela par la composition et, dans les rouages ​​internes des compilateurs, cela revient au même. Bien sûr, nous perdons la sécurité de type si nous voulons baisser le ton , et là, je dirais que si vous voulez être discret , il vous suffit de ne pas utiliser C pour cela, car ce que les gens font en C pour imiter le downcast peut être horrible d'un type sécurité, mais je préférerais que les gens ne soient pas abattus du tout. La sécurité de type est quelque chose que vous pouvez facilement commencer à manquer en C, car le compilateur offre une marge de manœuvre suffisante pour interpréter les choses sous forme de bits et d'octets, sacrifiant ainsi la possibilité de détecter les erreurs qui pourraient se produire au moment de la compilation, mais certains langages étaient considérés comme orientés objet. même pas statiquement tapé.

Donc, non, je pense que ça va. Bien sûr, je n’utiliserais pas C pour essayer de créer une base de code à grande échelle conforme aux principes de SOLID, mais cela n’est pas nécessairement dû à ses défauts dans le domaine orienté objet. Un grand nombre des fonctionnalités qui me manqueraient si j'essayais d'utiliser C à cette fin sont liées à des fonctionnalités de langage qui ne sont pas directement considérées comme une condition préalable à la POO, telles que la sécurité de type forte, les destructeurs qui sont automatiquement appelés lorsque des objets sortent de la portée, l'opérateur surcharge, modèles / génériques et traitement des exceptions. C'est quand je manque ces fonctionnalités auxiliaires que j'atteins pour C ++.


la source
1
Je ne sais pas comment les constructeurs ne pourraient pas être considérés comme une condition préalable à la POO. Une partie de l'essence de base de l'encapsulation est la capacité d'assurer des invariants pour un objet. Et cela nécessite de pouvoir initialiser correctement l’objet dans ces invariants. Cela nécessite un constructeur: une ou plusieurs fonctions, de sorte que vous ne pouvez pas encore dire que l'objet existe jusqu'à ce qu'au moins une d'entre elles ait été appelée.
Nicol Bolas
Lorsque nous avons des informations cachées avec des types opaques, le seul moyen de les instancier, de les copier / cloner et de les détruire, consiste à utiliser l'équivalent analogique de fonctions servant de constructeurs et de destructeurs tout en conservant la capacité de gérer ces invariants. Il est tout simplement pas modélisé directement dans la langue et peut ressembler à la forme de foo_createet foo_destroyet foo_clone, par exemple
Dans struct Fooun tel cas, tout ce dont nous avons besoin de conserver les invariants est de s’assurer que ses membres de données ne peuvent pas être consultés ni mutés par le monde extérieur, ce que donnent immédiatement les types opaques (déclarés mais non définis au monde extérieur). C'est sans doute une forme de dissimulation d'informations plus forte, comparable à celle d'un pimplC ++.
Oui, je sais comment les gens mettent en œuvre la POO en C, merci. Mon argument était que votre déclaration selon laquelle les constructeurs "ne sont pas directement considérés comme une condition préalable à la POO" est erronée.
Nicol Bolas
Je vois, je suppose que c'est correct ... mais dans ce cas, pourrions-nous dire que C fournit un support (adéquat?) Aux destructeurs et aux constructeurs?
-1

Pas une mauvaise question.

Si vous appelez c un langage OO, vous devez également appeler à peu près tous les langages procéduraux OO. Cela rendrait donc le terme vide de sens. c n’a pas de support linguistique pour OO. Si a des structures, mais les structures typesne sont pas des classes.

En fait, c n’a pas beaucoup de fonctionnalités comparées à la plupart des langues. Il est principalement utilisé pour sa rapidité, sa simplicité, sa popularité et son support, y compris des tonnes de bibliothèques.

Glen P
la source