IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Quelle est la meilleure manière de faire de la POO en C ?


Sujet :

C

  1. #21
    Membre à l'essai
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2018
    Messages
    28
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Cher (Centre)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Juillet 2018
    Messages : 28
    Points : 22
    Points
    22
    Par défaut
    Je croyais qu'il était impossible d’implémenter le "Run Time Type Identification" (je connaissais pas l'abréviation), et encore plus la réflexion, en C ? En objective-C tu parle des sélecteurs, n'est-ce pas ?

  2. #22
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 630
    Points : 10 556
    Points
    10 556
    Par défaut
    Citation Envoyé par ghost2002 Voir le message
    En objective-C tu parle des sélecteurs, n'est-ce pas ?
    Non, les sélecteurs sont des pointeurs de fonctions/ méthodes

    Je parle de (BOOL) respondsToSelector: (SEL) aSelector (<- lien Apple anglais et il y a aussi les "See Also" sur cette page)
    Et cela tu ne l'as pas en C++ et cela fait partie de la réflexion, comme la RTTI en fait partie.

  3. #23
    Expert éminent
    Avatar de Pyramidev
    Homme Profil pro
    Développeur
    Inscrit en
    Avril 2016
    Messages
    1 471
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 471
    Points : 6 110
    Points
    6 110
    Par défaut
    Dans une implémentation normale du C++, le RTTI se manifeste sous la forme d'un objet std::type_info stocké au début de la table virtuelle, juste avant la succession des adresses des fonctions virtuelles. On peut suivre la même stratégie en C.

  4. #24
    Membre à l'essai
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2018
    Messages
    28
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Cher (Centre)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Juillet 2018
    Messages : 28
    Points : 22
    Points
    22
    Par défaut
    Je parle de (BOOL) respondsToSelector: (SEL) aSelector (<- lien Apple anglais et il y a aussi les "See Also" sur cette page)
    c'est ce que je voulais dire (ça utilise bien les sélecteurs ). Pyramidev, aurais-tu un exemple ? Et dans le code que tu as poster, quelle stratégie te semble la meilleure ?

    PS: Que pensez-vous du code que j'ai poster ?

  5. #25
    Expert éminent
    Avatar de Pyramidev
    Homme Profil pro
    Développeur
    Inscrit en
    Avril 2016
    Messages
    1 471
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 471
    Points : 6 110
    Points
    6 110
    Par défaut
    Citation Envoyé par ghost2002 Voir le message
    Pyramidev, aurais-tu un exemple ?
    J'ai la flemme de coder le RTTI en C mais, dans les grandes lignes, voici comment on pourrait faire :
    • Le premier membre de chaque classe de base sans parent est un pointeur vers une table virtuelle.
    • Le premier membre de chaque classe dérivée est un objet dont le type est une classe de base directe.
    • Grâce aux deux points précédents, les 32 ou 64 premiers bits de tout objet de ces classes sont l'adresse d'une table virtuelle.
    • Chacune des tables virtuelles dont l'adresse peut être au début d'un objet ont pour premier membre un TypeInfo. Ainsi, à partir de tout pointeur vers un objet de ces classes, on peut accéder au TypeInfo correspondant.
    • TypeInfo contient un pointeur de type const TypeInfoImpl*.
    • TypeInfoImpl est une structure qui contient des informations sur le type, dont le nom du type et la liste des classes de base directes (par exemple sous la forme d'un tableau de TypeInfo).


    Citation Envoyé par ghost2002 Voir le message
    Et dans le code que tu as poster, quelle stratégie te semble la meilleure ?
    Si j'étais obligé de coder en C, alors je pense que la stratégie que j'utiliserais le plus souvent serait la programmation orientée protocole.
    Remarque : dans LoggerHandle, j'ai mis directement un pointeur de fonction, car il n'y avait qu'une seule fonction. Mais, s'il y avait eu trop de fonctions, alors j'aurais mis un pointeur vers une structure contenant les pointeurs de fonction afin que chaque LoggerHandle prenne moins de place.

    La programmation orientée objet dans le style C++ serait lourde à implémenter en C. En plus, cette forme de programmation orientée objet est moins flexible que la programmation orientée protocole car on ne peut ajouter un type parent à un type déjà existant sans modifier le code existant.

    Quant à la programmation générique à coup de macros, si on l'utilise trop, alors le code sera indébogable et lent à compiler.

    Citation Envoyé par ghost2002 Voir le message
    PS: Que pensez-vous du code que j'ai poster ?
    Il y a quelques erreurs de compilation (point-virgules manquants) mais, une fois que c'est corrigé, ça marche.

    Attention cependant à la gestion des erreurs :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    void test_set(struct Test_private *This, int i)
    {
           if (This)
           {
                  This->i = i;
           }
    }
    Si, par étourderie, This == NULL, alors le code ci-dessus repoussera l'erreur plus loin. Alors, quand cette erreur sera détectée, il sera plus difficile de remonter à l'origine de l'erreur. Une manière de traiter l'erreur serait d'écrire un message dans la sortie d'erreur puis éventuellement d'arrêter le programme.

    Personnellement, en C, comme il y a des pointeurs partout, j'adopte la convention suivante : tout pointeur est par défaut jamais nul. Si un pointeur peut être nul, alors je le signale explicitement par le nommage, par exemple avec un suffixe "OrNull". Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Car* carOrNull = Person_GetCarOrNull(person);
    Comme ça, je distingue du premier coup d’œil les pointeurs qui peuvent être nuls.

  6. #26
    Membre à l'essai
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2018
    Messages
    28
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Cher (Centre)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Juillet 2018
    Messages : 28
    Points : 22
    Points
    22
    Par défaut
    Je crois que je comprend à peut-près ce que tu explique, mais je vois pas ce que tu peux faire de ta structure . Concernant mon code, je l'ai écrit à la va vite pour vous montrer, mais si il fonctionne, je n'arrive pas à faire de l'héritage correctement, ni du polymorphisme...

  7. #27
    Membre à l'essai
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2018
    Messages
    28
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Cher (Centre)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Juillet 2018
    Messages : 28
    Points : 22
    Points
    22
    Par défaut
    Heu... Je suis toujours intéresser ! Particulièrement par l’implémentation d'un objet de base !

  8. #28
    Expert éminent
    Avatar de Pyramidev
    Homme Profil pro
    Développeur
    Inscrit en
    Avril 2016
    Messages
    1 471
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 471
    Points : 6 110
    Points
    6 110
    Par défaut
    Le RTTI permet de tester à l'exécution que le type X d'un certain objet obj dérive bien d'un certain type Y. En pratique, tu peux te passer du RTTI.

    En C++, le compilateur a besoin du RTTI pour implémenter le mécanisme des exceptions typées dynamiquement : pour savoir si un bloc catch(Y&) peut attraper une exception obj, il faut pouvoir tester à l'exécution si le type de obj dérive directement ou indirectement de Y. Pour comprendre cette phrase, il faut connaître au moins un langage qui utilise les exceptions pour la gestion des erreurs (ex : C++, Java, Python...).

    Pour implémenter l'héritage, si tu comprends les codes de dalfab et moi, normalement, tu devrais pouvoir implémenter l'héritage simple.

    Pour comprendre le code que j'ai écrit, il faut essayer de l'exécuter pas à pas dans la tête :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    void firstDemo() {
    	LoggerDeriv logger;
    	LoggerDerivCtor(&logger, stdout);
    	LoggerBase* loggerPtr = &logger.super;
    	LoggerLog(loggerPtr, "Object oriented programming.", LoggerLevel_Debug);
    }
    Point à retenir : le constructeur LoggerDerivCtor détermine la table virtuelle pointée :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void LoggerDerivCtor(LoggerDeriv* self, FILE* file) {
    	self->super.m_vtable = &loggerDerivVTable; // à se rappeler pour comprendre la suite
    	self->m_file = file;
    }
    Ensuite, LoggerLog fait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    void LoggerLog(LoggerBase* self, const char* msg, LoggerLevel level) {
    	self->m_vtable->m_log(self, msg, level);
    }
    Si on tient compte des informations précédentes, cet appel à LoggerLog fait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    loggerDerivVTable.m_log(loggerPtr, "Object oriented programming.", LoggerLevel_Debug);
    Quelle fonction pointe loggerDerivVTable.m_log ? On regarde le code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    LoggerVTable loggerDerivVTable = { &LoggerDerivLogWithCast };
    Ensuite, on lit la définition de LoggerDerivLogWithCast :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    void LoggerDerivLogWithCast(LoggerBase* self, const char* msg, LoggerLevel level) {
    	LoggerDerivLog((LoggerDeriv*) self, msg, level);
    }
    Donc, au final, l'appel à LoggerLog ci-avant fait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    LoggerDerivLog((LoggerDeriv*) loggerPtr, "Object oriented programming.", LoggerLevel_Debug);
    Et voilà, grâce au mécanisme des tables virtuelles, LoggerLog appelle la fonction LoggerDerivLog qui correspond bien au type réel (LoggerDeriv) de l'objet logger pointé par loggerPtr.

    Après avoir lu plusieurs fois, tu pourras maintenir en mémoire en même temps toutes les étapes qui transforment l'appel de LoggerLog en appel de LoggerDeriv. Alors, tu auras progressé dans la compréhension de l'implémentation de l'héritage simple (sans RTTI).

    Pour aller plus loin :
    Dans mon exemple simple, il n'y a besoin que d'un seul type de table virtuelle (LoggerVTable). Mais, si une classe OtherLogger qui dérive de LoggerBase possède plus de fonction virtuelles, alors il faudra créer un nouveau type (OtherLoggerVTable). Pour que ça marche, il faudra que le début de la structure OtherLoggerVTable corresponde à la structure LoggerVTable. Donc il faudra que le premier pointeur de fonction de OtherLoggerVTable corresponde à la fonction de log.

    Pour aller encore plus loin, tu pourras implémenter une classe de base avec un état, comme la classe Animal de dalfab qui stocke un nom.

    Encore plus loin, il y a l'héritage multiple. Mais, là, les choses se compliquent.

    Ou alors, il y a la programmation orientée protocole où la vie est simple. Pour comprendre le code que j'ai écrit, c'est la même méthode qu'avec le code firstDemo ci-avant (décortiquer les étapes puis essayer de tout maintenir en mémoire en même temps) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    void secondDemo() {
    	SimpleLogger logger;
    	SimpleLoggerCtor(&logger, stdout);
    	LoggerHandle loggerHandle;
    	LoggerHandleCtorSimpleLogger(&loggerHandle, &logger);
    	LoggerHandleLog(loggerHandle, "Protocol oriented programming.", LoggerLevel_Debug);
    }

  9. #29
    Membre à l'essai
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2018
    Messages
    28
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Cher (Centre)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Juillet 2018
    Messages : 28
    Points : 22
    Points
    22
    Par défaut
    Donc si j'ai bien compris la bonne idée c'est d'utiliser les protocoles ? Peut-on tirer quelque chose de mon code ? Comment je peut faire pour implémenter les fonction retain(), release(), copy(), hash(), ... de manière générique et threads-safe ? Comment faire pour vérifier la conformité d'un objet (qu'il propose bien les fonctions de base (implémenter comment ?) ou qu'il respecte bien un protocoles) ? Peut-on combiner protocoles et héritage ? Cela présente t'il un intérêt ? Et l'héritage multiple est t'il réellement quelque chose d’utile ? Et si oui comment l’implémenter ? Ou puis-je trouver des exemple de RTTI en C ? Comment python implémente les objets (En lisant les sources j'ai cru comprendre que tous les objets hérite de PyObject, qui doit être le premier membre pour être caster, mais ça me paraît pas très propre...) ? Est-ce une bonne solution ?

    Désolé, mais c'est un peut tout ce qui se bouscule dans ma cervelle actuellement

  10. #30
    Membre à l'essai
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2018
    Messages
    28
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Cher (Centre)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Juillet 2018
    Messages : 28
    Points : 22
    Points
    22
    Par défaut
    Pitiéééééééééééééééééé ! J'ai relu ton code vingt fois, et j'ai compris (eureka !). Mais je vois pas comment utiliser ces méthodes pour optimiser la programmation de ceux qui utiliseront ma lib ! Et encore moins comment obtenir le hash d'un objet ou gérer sa mémoire via retain() et release() (enfin si, je sais faire, mais pas threads-safe)...

  11. #31
    Expert éminent
    Avatar de Pyramidev
    Homme Profil pro
    Développeur
    Inscrit en
    Avril 2016
    Messages
    1 471
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 471
    Points : 6 110
    Points
    6 110
    Par défaut
    Citation Envoyé par ghost2002 Voir le message
    gérer sa mémoire via retain() et release() (enfin si, je sais faire, mais pas threads-safe)...
    Pour rendre cela thread-safe, une méthode simple serait que chaque objet contienne un mutex. Au début de retain et release, on bloque le mutex. À la fin, on le débloque.

    Mais pourquoi veux-tu gérer de la mémoire en C par du comptage de références ? Cela complexifie le code et réduit les performances, donc il faut une bonne raison.

    En C, la majorité du temps, c'est celui qui alloue une ressource qui la désalloue et il n'y a pas besoin de passer par du polymorphisme pour désallouer la ressource. Là où plus personne n'a besoin d'une certaine ressource, on appelle directement la bonne fonction de désallocation et c'est bon :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Resource myResource; // no polymorphic
    errorCode = ResourceCtor(&myResource, other parameters...); // allocation
    if(errorCode == 0) {
    	... // code which uses myResource
    	ResourceDtor(&myResource); // deallocation
    }
    Dans des cas plus rares, si on simule le patron de conception Fabrique, alors on a besoin du polymorphisme pour gérer la destruction, mais pas forcément du comptage de références :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    // Protocol-oriented programming
     
    typedef struct DestructibleLoggerHandle {
    	void* m_obj;
    	void(*m_log)(void* obj, const char* msg, LoggerLevel level);
    	void(*m_dtor)(void* obj);
    } DestructibleLoggerHandle;
     
    void DestructibleLoggerHandleLog(DestructibleLoggerHandle self, const char* msg, LoggerLevel level) {
    	self.m_log(self.m_obj, msg, level);
    }
     
    void DestructibleLoggerHandleDelete(DestructibleLoggerHandle self) {
    	self.m_dtor(self.m_obj);
    	free(self.m_obj);
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    DestructibleLoggerHandle owningLoggerHandle; // polymorphic
    errorCode = CreateDestructibleLoggerByName(&owningLoggerHandle, loggerName); // allocation
    if(errorCode == 0) {
    	... // code which uses owningLoggerHandle
    	DestructibleLoggerHandleDelete(owningLoggerHandle); // polymorphic deallocation
    }

  12. #32
    Membre à l'essai
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2018
    Messages
    28
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Cher (Centre)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Juillet 2018
    Messages : 28
    Points : 22
    Points
    22
    Par défaut
    Je sais qu'on peut utiliser les mutex, mais tu es d'accord qu'avant de libérer la mémoire allouer à l'objet, le destructeur détruit le mutex ? Il se passe quoi si un thread accède à l'objet à ce moment précis, celui ou le mutex est détruit, mais l'objet pas encore NULL ? Et quand au pourquoi, je pense pas que ce soit une mauvaise de rester dans la logique objective-C... Même si pour l'instant j'ai pas grand chose de concret...

  13. #33
    Expert éminent
    Avatar de Pyramidev
    Homme Profil pro
    Développeur
    Inscrit en
    Avril 2016
    Messages
    1 471
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 471
    Points : 6 110
    Points
    6 110
    Par défaut
    Effectivement, si l'objet contient le mutex et si release décide qu'il faut détruire l'objet car le compteur de références tombe à zéro, alors il faut d'abord libérer le mutex avant de détruire l'objet. Donc, dans ce cas, la libération du mutex ne se fait pas complètement à la fin de l'appel de release.

    Mais, sauf erreur de programmation, il n'y a pas de risque qu'un autre thread accède à l'objet entre le moment où on libère le mutex et celui où on détruit l'objet. En effet, on ne décide de le détruire que quand le compteur de références est à zéro. Or, si un autre thread veut accéder à l'objet, alors le compteur de références ne devrait pas être à zéro.

  14. #34
    Membre à l'essai
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2018
    Messages
    28
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Cher (Centre)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Juillet 2018
    Messages : 28
    Points : 22
    Points
    22
    Par défaut
    C'est pas une erreur de programmation que deux threads nouvellement créés tentent d'accéder à une variable globale qui n'est plus utiliser par leurs "collèges"... Cela signifie compteur égal à zéro et objet pas forcément égale à NULL... Non ?

  15. #35
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 630
    Points : 10 556
    Points
    10 556
    Par défaut
    Citation Envoyé par ghost2002 Voir le message
    C'est pas une erreur de programmation que deux threads nouvellement créés tentent d'accéder à une variable globale qui n'est plus utiliser par leurs "collèges"
    C'est pour cela que ce que tu veux faire en langage C c'est tout sauf trivial/ simple/ rapide à coder

    Pour moi le problème c'est de mettre un appel à delete dans le release (appel lorsque le compteur est à zéro)
    Il faudrait voir comment, par exemple, l'interface IUnknown de COM a été codée.

    Mais pour moi, il faut commencer à faire un ramasse-miettes (RM) en séparant d'une part une interface MyObjet retain - release (une espèce de table de pointeurs) et de l'autre l'objet lui même avec un accès protégé/ privé (seul le RM peut le créer, le détruire (c'est ce RM qui vérifie le compteur de ton objet) et transmettre son interface MyObjet si ton objet y adhére).

    Le problème du langage C c'est que tu n'as pas de collections, la gestion des threads est bas niveau et que niveau accès (mémoire/ objet/ ...) c'est par défaut "open bar".
    Tu parles de variables globales : même si tu peux y arriver comme cela, je pense que dès le départ il ne faut surtout pas y penser.

  16. #36
    Membre à l'essai
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2018
    Messages
    28
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Cher (Centre)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Juillet 2018
    Messages : 28
    Points : 22
    Points
    22
    Par défaut
    Je t'arrête ! Je parle de variables globales uniquement pour illustrer mon propos, il n'était pas question d’implémentation ! Je connait pas du tout COM (C'est une technologie Microsoft, non ?)... Pourrais-tu m'en dire plus sur ce que c'est et surtout sur l'implémentation dont tu parles ? Et aurais-tu un exemple de ce que tu proposes, d'autant que je pense que c'est précisément ce que je cherche ? Et j'ai bien compris que c'est hardcore, sinon je serais pas en train de vous embêtez !

  17. #37
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 690
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 690
    Points : 30 985
    Points
    30 985
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par ghost2002 Voir le message
    Quelle est la meilleure manière de faire de la POO en C ?
    Le faire bien

    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  18. #38
    Expert éminent
    Avatar de Pyramidev
    Homme Profil pro
    Développeur
    Inscrit en
    Avril 2016
    Messages
    1 471
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 471
    Points : 6 110
    Points
    6 110
    Par défaut
    @ghost2002 :

    Si deux threads essaient d'accéder à un même objet dont la mémoire est gérée par un compteur de références, si seuls ces deux threads ont besoin de cet objet, si tu ne sais pas lequel de ces deux threads se termine en dernier et si tu veux que l'objet soit détruit dès qu'aucun des deux threads n'a besoin de l'objet, alors chacun de ces threads doit posséder l'objet tant qu'il en a encore besoin. Donc, tant que les deux en ont besoin, le compteur de références vaut au moins 2. Sinon, il y a une erreur de programmation dans le code utilisateur. Le compteur de références ne passe alors à 1 que quand il ne reste qu'un seul thread qui connaît l'objet.

    Si deux threads ont besoin d'accéder à un même objet dont le compteur de références vaut 1, alors ça veut dire qu'un seul des deux threads possède l'objet. L'autre thread connaît l'adresse de l'objet, mais sans que cette adresse ne compte dans le compteur de références. Alors, le code appelant doit s'assurer que le thread qui ne possède pas l'objet n'essaie plus d'y accéder quand l'autre thread aura détruit l'objet. Sinon, cela veut dire qu'il y a une erreur de programmation dans le code utilisateur.

    Cela dit, je maintiens que tu te compliques la vie. Le C n'a de sucre syntaxique ni sur l'orienté objet, ni sur la gestion de la mémoire à coup de comptage de références.

  19. #39
    Membre à l'essai
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2018
    Messages
    28
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Cher (Centre)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Juillet 2018
    Messages : 28
    Points : 22
    Points
    22
    Par défaut
    Excuse moi, mais je vois toujours le même problème: Si un seul thread à l'objet et qu'il détruit le mutex pour le libérer, que va t'il se passer si des threads nouvellement créés essayent d'y accéder précisément à ce moment ? Parce que on à un mutex invalide, et un objet pas encore égal à NULL, et donc qu'on est sensé pouvoir utiliser...

    S'ils vous plaît, personne n'a d'idée pour implémenter un objet racine et vérifié qu'il est bien hérité par les autres ?

    PS: L’implémentation PHP m'a l'air beaucoup plus propre et complexe que celle de python... Ça inspire quelqu'un ?

  20. #40
    Expert éminent sénior
    Avatar de Kannagi
    Homme Profil pro
    cyber-paléontologue
    Inscrit en
    Mai 2010
    Messages
    3 214
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : cyber-paléontologue

    Informations forums :
    Inscription : Mai 2010
    Messages : 3 214
    Points : 10 140
    Points
    10 140
    Par défaut
    Évite les Up , si personne ne répond c'est que personne n'a les réponses ou que les gens sont occupé.
    Mon conseille est tout de même que quand on fait des choses en dehors des clous , il faudra apprendre a se débrouiller un peu seul !

    De manière perso , je trouve cela totalement inutile , déjà parce le C avec objet c'est super moche , que de deux la solution a mes problèmes sont pas souvent d'ordre de paradigme , et trois que le C++ existe et il le fait mieux sans parler de toute les nouveauté que le C++ apporte

Discussions similaires

  1. Réponses: 16
    Dernier message: 18/08/2008, 18h29
  2. Quelle est la meilleure maniere de faire une count?
    Par farenheiit dans le forum Administration
    Réponses: 20
    Dernier message: 16/11/2007, 16h45
  3. Réponses: 3
    Dernier message: 09/11/2007, 15h38
  4. Réponses: 2
    Dernier message: 19/03/2007, 16h41
  5. Copie disque à disque. Quelle est la meilleur manière ?
    Par olive_le_malin dans le forum Autres Logiciels
    Réponses: 20
    Dernier message: 19/02/2006, 00h32

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo