170 votes

Orientation objet en C

Quelqu'un pourrait-il partager un ensemble d'astuces de préprocesseur (compatible ANSI C89/ISO C90, s'il vous plaît) qui permettent une sorte d'orientation objet moche (mais utilisable) en C ? Je suis familier avec quelques langages orientés objet différents, alors s'il vous plaît, ne répondez pas par des réponses du type "Apprenez le C++". J'ai lu " Programmation orientée objet avec ANSI C "(Attention : pdf ) et plusieurs autres solutions intéressantes, mais je suis surtout intéressé par la vôtre :-) !


Voir aussi Pouvez-vous écrire du code orienté objet en C ?

1 votes

Je peux répondre pour apprendre le D et utiliser le c compatible abi pour les endroits où tu as vraiment besoin du C. digitalmars.com/d

0 votes

Pas vraiment. Je travaille avec des systèmes embarqués qui n'ont qu'un compilateur C à leur disposition.

2 votes

@Dinah : Merci pour le "Voir aussi". Ce billet était intéressant.

1voto

jmucchiello Points 10521

Si je devais écrire de la POO en C, j'opterais probablement pour une conception pseudo-PIMPL. Au lieu de passer des pointeurs vers des structs, vous finissez par passer des pointeurs vers des pointeurs vers des structs. Cela rend le contenu opaque et facilite le polymorphisme et l'héritage. Le vrai problème de la POO en C est ce qui se passe lorsque les variables sortent de la portée. Il n'y a pas de destructeurs générés par le compilateur et cela peut causer des problèmes. Les MACROS peuvent éventuellement aider mais ce sera toujours laid à regarder.

1 votes

Lorsque je programme en C, je gère la portée en utilisant if et les libérer à la fin. Par exemple if ( (obj = new_myObject()) ) { /* code using myObject */ free_myObject(obj); }

1voto

rogergc Points 11
#include "triangle.h"
#include "rectangle.h"
#include "polygon.h"

#include <stdio.h>

int main()
{
    Triangle tr1= CTriangle->new();
    Rectangle rc1= CRectangle->new();

    tr1->width= rc1->width= 3.2;
    tr1->height= rc1->height= 4.1;

    CPolygon->printArea((Polygon)tr1);

    printf("\n");

    CPolygon->printArea((Polygon)rc1);
}

Sortie :

6.56
13.12

Voici une démonstration de ce qu'est la programmation OO avec C.

C'est du vrai, du pur C, pas de macros de préprocesseur. Nous avons l'héritage, le polymorphisme et l'encapsulation des données (y compris les données privées aux classes ou aux objets). Il n'y a aucune chance pour que le qualificatif protected soit équivalent, c'est-à-dire, les données privées sont également privées en aval de la chaîne d'héritage. Mais ce n'est pas un inconvénient car je ne pense pas que cela soit nécessaire.

CPolygon n'est pas instancié car nous ne l'utilisons que pour manipuler des objets de la chaîne d'héritage qui ont des aspects communs mais une implémentation différente (Polymorphisme). mais dont l'implémentation est différente (polymorphisme).

0 votes

Je pense que cette réponse obtiendrait beaucoup plus de votes +1 si elle comportait un exemple d'implémentation, plutôt qu'un simple exemple d'utilisation. Je peux imaginer une mise en œuvre, mais seulement parce que j'y ai déjà beaucoup réfléchi et que j'ai appris d'autres mises en œuvre du C orienté objet. Quelqu'un qui se pose encore la question ci-dessus n'aura pas la même facilité à trouver comment le faire.

0 votes

Cela dit, +1 de ma part, car il s'agit, de manière subtile, d'une variation différente de toutes les réponses ci-dessus, qui, à première vue, semble avoir quelques avantages possibles par rapport aux autres réponses.

0voto

FL4SOF Points 705

Pour moi, l'orientation objet en C devrait avoir ces caractéristiques :

1) encapsulation et masquage des données (peut être réalisé en utilisant des structs/pointeurs opaques)

2) héritage et support du polymorphisme ( l'héritage simple peut être réalisé en utilisant des structs - assurez-vous que la base abstraite n'est pas instanciable)

3) fonctionnalité de constructeur et destructeur (pas facile à réaliser)

4) vérification des types (au moins pour les types définis par l'utilisateur car le C n'en impose pas)

5) comptage des références (ou quelque chose pour implémenter le RAAI)

6) support limité pour la gestion des exceptions (setjmp et longjmp )

en plus de ce qui précède, il devrait s'appuyer sur les spécifications ANSI/ISO et ne devrait pas s'appuyer sur des fonctionnalités spécifiques au compilateur.

0 votes

Pour le numéro (5) - Vous ne pouvez pas implémenter RAII dans un langage sans destructeurs (ce qui signifie que RAII n'est pas une technique supportée par le compilateur en C ou en Java).

0 votes

Les constructeurs et les destructeurs peuvent être écrits pour les objets basés sur le C - je suppose que GObject le fait. Et bien sûr RAAI (ce n'est pas simple, cela peut être laid et n'a pas besoin d'être pragmatique du tout) - tout ce que je cherchais, c'était à identifier la sémantique basée sur le C pour atteindre ce qui précède.

0 votes

Le C ne supporte pas les destructeurs. Vous devez taper quelque chose afin de les faire fonctionner. Cela signifie qu'ils ne se nettoient pas eux-mêmes. GObject ne change pas le langage.

0voto

onmyway133 Points 2196

@Adam Rosenfield a une très bonne explication sur la façon de réaliser la POO avec le C.

Par ailleurs, je vous recommande de lire

1) pjsip

Une très bonne bibliothèque C pour la VoIP. Vous pouvez apprendre comment elle réalise la POO à travers les structures et les tables de pointeurs de fonctions.

2) iOS Runtime

Apprenez comment le Runtime d'iOS fait fonctionner l'Objective C. Il réalise la POO grâce à isa pointer, meta class

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