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

Langage C++ Discussion :

Fabrique et RAII


Sujet :

Langage C++

  1. #1
    Membre régulier
    Homme Profil pro
    Ingénieur validation
    Inscrit en
    Août 2018
    Messages
    37
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur validation
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2018
    Messages : 37
    Points : 123
    Points
    123
    Par défaut Fabrique et RAII
    Bonsoir

    Après avoir lu : https://www.developpez.net/forums/d1...tion-pointeur/

    Je suis en train de porter du code C# en C++.
    Mon souci est de convertir ce qui ressemble fortement à un pattern Fabrique et d'y appliquer au mieux le RAII, qui n'est évidemment pas utilisé en C#.

    Dans le code original, j'ai une méthode qui me renvoie un objet (en fait une référence implicite) d'une classe abstraite. L'objet réel étant une instance d'une classe concrète construit dans la Fabrique et qui sera nettoyé par le GC.
    En C++, pas possible de renvoyer une référence sur un objet qui serait détruit dès la sortie de portée de la méthode Fabrique. Je renvoie donc un pointeur et l'objet appelant a la charge de le détruire. C'est pas du tout RAII et exception-safe.

    Si j'ai bien compris, en C++11, unique_ptr permet d'encapsuler construction et destruction automatique. Mais cette classe a bien une sémantique d'entité. Comment la mettre en résultat de fonction qui, par définition, fait une copie?
    Et comment se débrouiller en C++98/03 ?
    L'idéal est donc au moins de séparer ce qui construit de tes ressources de ce qui les maintient en mémoire
    Je ne suis pas sûr de comprendre, on cherche bien à ce que l'objet qui alloue la mémoire soit responsable de la restituer automatiquement dans son destructeur.

    Une Fabrique RAII exige-t-elle donc de pouvoir utiliser la sémantique de déplacement et donc le C++11 a minima ?

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par Grool Voir le message
    Comment la mettre en résultat de fonction qui, par définition, fait une copie?
    C'est pour ça que C++11 vient avec la sémantique de déplacement. Et return en tirera profit.
    Citation Envoyé par Grool Voir le message
    Et comment se débrouiller en C++98/03 ?
    Tu peux très bien créer ton propre scoped_ptr ou nom de ton choix qui mimique unique_ptr. La majorité des codebases que j'ai vu datant d'avant C++11 ont un tel objet.

    Citation Envoyé par Grool Voir le message
    Une Fabrique RAII exige-t-elle donc de pouvoir utiliser la sémantique de déplacement et donc le C++11 a minima ?
    Y'a aucune exigence mais avec C++11 c'est instantanné et marche directement. Avec les versions précédentes il faut bricoler toi-même.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  3. #3
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Tu peux faire du RAII avant C++11, mais il y a certains points où tu seras limité (ou alors où le code sera facile à mal écrire).

    Au moment où tu crées l'objet, et éventuellement le configure, il est logique que ce soit ta Fabrique qui possède l'objet.
    Une fois cette construction finie, il devient logique que ce soit l'utilisateur qui le possède.

    Il n'y a donc pas trop le choix: Soit la propriété est transférée de l'un à l'autre (c'est ce que fait la sémantique de mouvement sur un unique_ptr), soit la propriété est partagée entre les deux (c'est ce que ferait un shared_ptr, avec tous les problèmes liés à une copropriété).

    Maintenant, on est en 2018, C++11 devrait être un acquis un peu partout, non ?
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  4. #4
    Membre régulier
    Homme Profil pro
    Ingénieur validation
    Inscrit en
    Août 2018
    Messages
    37
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur validation
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2018
    Messages : 37
    Points : 123
    Points
    123
    Par défaut
    Merci pour ces réponses.

    Maintenant, on est en 2018, C++11 devrait être un acquis un peu partout, non ?
    Certes... Je m'attendais bien à cette remarque. Mais je dispose d'un Visual C++ 2010 Pro dont le support de C++11 est incomplet (et y a peu de chance qu'on m'achète une licence plus récente).

    Cela dit, j'envisage sérieusement d'essayer quelque chose de plus moderne à titre personnel. Eclipse CDT notamment.

  5. #5
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Toutes les versions récentes de VS ont une version Community, totalement gratuite et qui est exactement identique à la version pro. (la seule différence doit être l'interdiction de commercialiser des programmes faits sous Community je pense, comme les Express auparavant).
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  6. #6
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Et j'utilise depuis quelques jours la version 2017 et je suis bien surpris des progrès par rapport à la version 2013 ou 2015 que j'utilisais il y un an dans ma précédente mission

  7. #7
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Citation Envoyé par Bousk Voir le message
    Toutes les versions récentes de VS ont une version Community, totalement gratuite et qui est exactement identique à la version pro. (la seule différence doit être l'interdiction de commercialiser des programmes faits sous Community je pense, comme les Express auparavant).
    C'est même autorisé de commercialisé des produits faits avec la version community, sous certaines conditions (en gros, particuliers, très petites entreprises) :
    https://visualstudio.microsoft.com/f...rms/mlt553321/

    Après, il faut payer. Mais franchement, je pense que le gain en productivité vaut souvent la chandelle (pas forcément le gain entre une community et une version plus luxueuse, ça dépend des usages, mais bien le gain entre une version 2010 et une version 2018).
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  8. #8
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,
    Citation Envoyé par JolyLoic Voir le message
    Après, il faut payer. Mais franchement, je pense que le gain en productivité vaut souvent la chandelle (pas forcément le gain entre une community et une version plus luxueuse, ça dépend des usages, mais bien le gain entre une version 2010 et une version 2018).
    +150 000!!!
    Quand je vois que C++11 n'a pas été correctement respecté jusqu'aux versions 2017 (si pas même 2018), entre autres, pour les fonctions =delete et=default, je ne peux qu'être pleinement d'accord avec toi
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  9. #9
    Membre régulier
    Homme Profil pro
    Ingénieur validation
    Inscrit en
    Août 2018
    Messages
    37
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur validation
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2018
    Messages : 37
    Points : 123
    Points
    123
    Par défaut
    Bonjour

    J'ai donc commencé mes essais d'Eclipse CDT en m'inspirant de ma préoccupation du moment : le pattern Factory Method du GoF.
    Code Product.h : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    #include <iostream>
     
    #ifndef PRODUCT_H_
    #define PRODUCT_H_
     
    namespace DesignPatterns {
     
        class Product {
        public:
    	Product();
    	virtual ~Product();	
    	virtual void Identite() = 0;
        };
    }
    #endif
    Code Product.cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #include "Product.h"
     
    namespace DesignPatterns {
        Product::Product() {
    	std::cout << "Construction Product Abstrait" << std::endl;
        }
        Product::~Product() {
    	std::cout << "Destruction Product Abstrait" << std::endl;
        }
    }
    Code ConcreteProduct.h : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    #ifndef CONCRETEPRODUCT_H_
    #define CONCRETEPRODUCT_H_
     
    #include "Product.h"
     
    namespace DesignPatterns {
     
        class ConcreteProduct: public Product {
        public:
    	ConcreteProduct();
    	~ConcreteProduct();
    	void Identite();
        };
    }
    #endif
    Code ConcreteProduct.cpp : 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
    #include "ConcreteProduct.h"
     
    namespace DesignPatterns {
        ConcreteProduct::ConcreteProduct() {
    	std::cout << "Construction ConcreteProduct" << std::endl;
        }
        ConcreteProduct::~ConcreteProduct() {
    	std::cout << "Destruction ConcreteProduct" << std::endl;
        }
        void ConcreteProduct::Identite(){
    	std::cout << "Je suis un Produit concret" << std::endl;
        }
     
     
    	void Identite();
    }
    Code Creator.h : 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
    17
    #ifndef CREATOR_H_
    #define CREATOR_H_
     
    #include <memory>
    #include "Product.h"
     
    namespace DesignPatterns {
     
        class Creator {
        public:
    	Creator();
    	virtual ~Creator();
     
    	virtual std::unique_ptr<Product> Factory() = 0;
        };
    }
    #endif
    Code Creator.cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #include "Creator.h"
     
    namespace DesignPatterns {
        Creator::Creator() {
    	std::cout << "Construction Creator Abstrait" << std::endl;
        }
        Creator::~Creator() {
    	std::cout << "Destruction Creator Abstrait" << std::endl;
        }
    }
    Code ConcreteCreator.h : 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
    #ifndef CONCRETECREATOR_H_
    #define CONCRETECREATOR_H_
     
    #include "Creator.h"
     
    namespace DesignPatterns {
     
        class ConcreteCreator: public Creator {
        public:
    	ConcreteCreator();
    	~ConcreteCreator();
     
    	std::unique_ptr<Product> Factory();
        };
    }
    #endif
    Code ConcreteCreator.cpp : 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
    #include "ConcreteCreator.h"
    #include "ConcreteProduct.h"
     
    namespace DesignPatterns {
        ConcreteCreator::ConcreteCreator() {
    	std::cout << "Construction ConcreteCreator" << std::endl;
        }
        ConcreteCreator::~ConcreteCreator() {
    	std::cout << "Destruction ConcreteCreator" << std::endl;
        }
     
        std::unique_ptr<Product> ConcreteCreator::Factory(){
    	std::unique_ptr<Product> pTempProduit = std::make_unique<ConcreteProduct>();
    	return pTempProduit ;
        }
    }
    Code Main.cpp : 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
    17
    18
    19
    #include "ConcreteCreator.h"
     
    using namespace DesignPatterns;
     
    void TestPattern(){
    	std::unique_ptr<Product> pProduit;
    	{
    		std::unique_ptr<Creator> pFab = std::make_unique<ConcreteCreator>();
    		pProduit = pFab->Factory();
    	}
    // ...Utilisation de pProduit ...
    	std::cout << "Utilisation du Produit..." << std::endl;
    	pProduit -> Identite();
    }
     
    int main(){
    	TestPattern();
    	return 0;
    }

    Résultat :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Construction Creator Abstrait
    Construction ConcreteCreator
    Construction Product Abstrait
    Construction ConcreteProduct
    Destruction ConcreteCreator
    Destruction Creator Abstrait
    Utilisation du Produit...
    Je suis un Produit concret
    Destruction ConcreteProduct
    Destruction Product Abstrait
    Mon produit n'est construit qu'une fois, pas d'objet temporaire ni de copie, et détruit automatiquement.
    Par contre, je n'ai pas étudié ce qu'il se passe si une exception surgit dans un constructeur.

    Le code que je porte n'est toutefois pas exactement une Factory GoF. Il ne comporte pas de "Creator", la classe mère "Product" expose une méthode statique qui choisit quel type de classe fille elle doit fabriquer.
    Ce n'est pas conforme au Dependency inversion principle mais ça peut éventuellement se justifier dans mon cas précis.

    Ma classe est un lecteur de fichier structuré qui expose des méthodes pour lire des éléments du fichier et gère un flux sous-jacent.
    Les classes qui appellent ce lecteur s'occupent de parser le fichier selon leur logique métier propre.
    Ce lecteur de fichier est spécialisé en classes filles pour lire soit un fichier texte ASCII, UTF16 soit un fichier binaire, le contenu est parfois compressé en ZLIB (ce qui me permettra aussi de réfléchir au Pattern Décorateur).
    La méthode "Factory" lit donc l'entête du fichier et crée le lecteur spécialisé qui convient. Ce comportement me semble suffisamment invariant pour ne pas devoir reprendre complètement l'architecture.

    Je testerai Visual C++ Community à l'occasion.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Fabriquer des requêtes sql à partir d'un document xml
    Par ktel dans le forum XQUERY/SGBD
    Réponses: 4
    Dernier message: 18/10/2005, 16h45
  2. RAII et virtual
    Par buzzz dans le forum C++
    Réponses: 3
    Dernier message: 22/02/2005, 14h51
  3. [GOF] Fabrique abstraite peut-elle être un Singleton ?
    Par manel007 dans le forum Design Patterns
    Réponses: 7
    Dernier message: 06/01/2005, 10h02
  4. [GOF] [Fabrique Abstraite] [Pont] Questions ?
    Par manel007 dans le forum Design Patterns
    Réponses: 5
    Dernier message: 04/01/2005, 20h18
  5. fabriquer un .X
    Par Fikus dans le forum DirectX
    Réponses: 4
    Dernier message: 23/03/2004, 15h24

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