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 :

Constructeur Destructeur MySQL


Sujet :

Langage C++

  1. #1
    Membre régulier
    Inscrit en
    Juin 2005
    Messages
    72
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 72
    Points : 70
    Points
    70
    Par défaut Constructeur Destructeur MySQL
    Bonjour à tous,

    J'ai développé une classe permettant un accès à MySQL.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class mysql{
    private:
    	sql::Driver *driver;
    	sql::Connection *con;
    	sql::Statement *stmt;
    	sql::ResultSet  *res;
     
    public:
    	mysql();
    	~mysql();
    	void selectDataBase(string);
    	void useProcedureToInsert(vector<string>, string);
    };

    Dans le constructeur je fais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    mysql::mysql(){
    	driver = get_driver_instance();
    	con = driver -> connect(DBHOST, USER, PASSWORD);
    	stmt = con->createStatement();
    	stmt->execute("USE MaDB");
    	stmt->execute("SET SESSION sql_mode = 'ANSI'");
    }
    Dans le destructeur je fais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    mysql::~mysql(){
    	delete res;
    	delete stmt;
    	delete con;
    }


    Quand le destructeur est appelé, il y a une exception de générée. Et là je ne vois pas pourquoi
    Si quelqu'un a une explication.....

    D'avance merci
    Cordialement

  2. #2
    Alp
    Alp est déconnecté
    Expert éminent sénior

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Points : 11 860
    Points
    11 860
    Par défaut
    Quelle est l'exception ?

  3. #3
    zul
    zul est déconnecté
    Membre éclairé Avatar de zul
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    498
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 498
    Points : 699
    Points
    699
    Par défaut
    Un destructeur avec des delete, et pas de constructeur par copie, ni de surcharge de =, ça sent le "double delete" à plein nez.

    Une bonne règle en général, c'est que si ton destructeur est non-trivial, il faut surcharger manuellement le constructeur par copie, et l'opérateur =, sinon elles copient bêtement les pointeurs.

  4. #4
    Membre confirmé
    Inscrit en
    Août 2004
    Messages
    556
    Détails du profil
    Informations forums :
    Inscription : Août 2004
    Messages : 556
    Points : 588
    Points
    588
    Par défaut
    Une bonne règle de programmation est de respecter la RAII: celui qui a crée est celui qui doit détruire. Or, dans ta classe mysql, je ne vois aucun new.

    Ton destructeur devrait plutôt ressembler à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    mysql::~mysql(){
    	stmt->releaseResultSet( res );    // détruit res
            con->releaseStatement( stmt );  // détruit stmt
            driver->disconnect( con );         // détruit con
    }
    Ces méthodes pourraient ressembler à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Connection::releaseStatement( Statement *& stmt )
    {
            if( stmt )
            {
                    delete stmt;
                    stmt = 0;
            }
    }
    ...
    Tu peux bien sûr améliorer le système en implémentant un système de tracage des objets créer, mais le mieux reste l'utilisation de pointeurs intelligent.

    Sinon, comme déjà dit, il faut que tu définisse le constructeur par copie.

  5. #5
    Membre régulier
    Inscrit en
    Juin 2005
    Messages
    72
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 72
    Points : 70
    Points
    70
    Par défaut
    Salut à tous :-)

    Alp, je n'ai pas réussi à capturer l'exception même en mettant un bloc catch (...) dans le main.

    Que signifie RAII ?

    Visiblement si une exception a été émise parce que le delete ne fonctionne pas, je suppose que les déclarations ne sont pas des allocations dynamiques.

    Y'a un truc que je ne comprend pas. Dans le code ci-dessous
    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
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    int main (){
    	sql::Driver *driver;
    	sql::Connection *con;
    	sql::Statement *stmt;
    	sql::ResultSet  *res;
     
     
    	try {
     
    		driver = get_driver_instance();
    		con = driver -> connect(DBHOST, USER, PASSWORD);
    		stmt = con->createStatement();
    		stmt->execute("USE MaDB");
     
    		res = stmt->executeQuery("SELECT ID, NOM, PRENOM FROM MaDB ORDER BY id ASC");
    		while (res->next()) {
    			cout << res->getInt("ID")	<< "\t" << res->getString("NOM") << "\t" << res->getString("PRENOM") << endl;
    		}
     
     
    	} catch (sql::SQLException &e) {
    		cout << "ERROR: SQLException in " << __FILE__;
    		//cout << " (" << __func__<< ") on line " << __LINE__ << endl;
    		cout << "ERROR: " << e.what();
    		cout << " (MySQL error code: " << e.getErrorCode();
    		cout << ", SQLState: " << e.getSQLState() << ")" << endl;
     
    		if (e.getErrorCode() == 1047) {
    			/*
    			Error: 1047 SQLSTATE: 08S01 (ER_UNKNOWN_COM_ERROR)
    			Message: Unknown command
    			*/
    			cout << "\nYour server does not seem to support Prepared Statements at all. ";
    			cout << "Perhaps MYSQL < 4.1?" << endl;
    		}
     
    		return EXIT_FAILURE;
    	} catch (std::runtime_error &e) {
     
    		cout << "ERROR: runtime_error in " << __FILE__;
    		//cout << " (" << __func__ << ") on line " << __LINE__ << endl;
    		cout << "ERROR: " << e.what() << endl;
     
    		return EXIT_FAILURE;
    	}catch(...){
    		return EXIT_FAILURE;
    	}
     
    	delete res;
    	delete stmt;
    	delete con;
     
    	system("PAUSE");
     
     
    	return EXIT_SUCCESS;
    }
    à la fin on fait bien un delete.
    Quelle est la différence entre le code de test ci-dessus et celui posté dans le message principal ?

    Désolé, c'est peut être simple pour vous, moins pour moi

    Merci

  6. #6
    Membre confirmé
    Inscrit en
    Août 2004
    Messages
    556
    Détails du profil
    Informations forums :
    Inscription : Août 2004
    Messages : 556
    Points : 588
    Points
    588
    Par défaut
    RAII = Ressource Acquisition Is Initialisation, et un de ses principes, entre autres, est que c'est celui qui a alloué un objet, ou instancié un objet qui doit le détruire.

    Pour les objets statiques, ça marche tout seul grâce au stack, mais il faut l'implémenter si tu utilises des pointeurs. Ou mieux, utiliser des pointeurs intelligents, qui vont se détruire eux même quand ils ne seront plus référencés.

    Je t'ai conseillé d'implémenter la déstruction de tes objets du côté de sql::, vu que tu les crées par leur biais.

  7. #7
    Membre régulier
    Inscrit en
    Juin 2005
    Messages
    72
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 72
    Points : 70
    Points
    70
    Par défaut
    Hello :-)

    Bon en fait je ne suis pas sûr de tout avoir compris.
    JulienDuSud, ce que tu me proposes signifie que je devrais faire 4 nouvelles classes héritant respectivement de "Driver, Connection, Statement, ResultSet" pour y implémenter les méthodes que tu proposes.

    J'ai donc fais cela
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    mysql::~mysql(){
    	res->close();
    	stmt->close();
    	con->close();
    }

    Pour ce qui est des attributs, je suppose que leurs destructeurs respectifs sont appelés lorsque mon objet mysql se termine.

  8. #8
    Membre confirmé
    Inscrit en
    Août 2004
    Messages
    556
    Détails du profil
    Informations forums :
    Inscription : Août 2004
    Messages : 556
    Points : 588
    Points
    588
    Par défaut
    Attention, si tu dérives d'une classe que tu n'as pas crée, il faut que tu t'assuers qu'elle est complètement virtuelle afin d'assurer la compatibilité.

    Si les méthodes que j'ai décrite n'existent pas dans ta librairie, c'est qu'elle est mal conçue de base. En réalité, des méthodes "close()" ne devraient même pas exister dans un code source bien conçu, du moins en C++.

    C'est la classe qui crée qui doit tracer les pointeurs qu'il crée afin de pouvoir les nettoyer correctement.

  9. #9
    Membre régulier
    Inscrit en
    Juin 2005
    Messages
    72
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 72
    Points : 70
    Points
    70
    Par défaut
    Hello :-)

    Je pense que le connecteur C++ pour MySQL a été bien conçu. Enfin je le souhaite.

    En fait pour être sûr que les objets soient bien détruits, il faudrait que je trouve un outils qui puisse détecter les fuites mémoires. Je crois avoir vu une fois ce genre d'outil quelque part.

    En tout cas merci pour ton aide

  10. #10
    Alp
    Alp est déconnecté
    Expert éminent sénior

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Points : 11 860
    Points
    11 860
    Par défaut
    Ou sinon, comme dit plus haut, t'appliques le RAII...

  11. #11
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par Alp Voir le message
    Ou sinon, comme dit plus haut, t'appliques le RAII..
    Et pour préciser le RAII, quelques lectures :
    F.A.Q. : Comment gérer proprement des allocations / désallocations de ressources : le RAII
    Tutoriel : Gérer ses ressources de manière robuste en C++, par Aurélien Regat-Barrel
    Tutoriel : Pointeurs intelligents, par Loïc Joly

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

Discussions similaires

  1. Réponses: 5
    Dernier message: 03/11/2008, 19h27
  2. [Débutant] Constructeur ~Destructeur
    Par grabriel dans le forum C++
    Réponses: 9
    Dernier message: 19/05/2008, 18h14
  3. aide pour constructeur destructeur
    Par aliwatte dans le forum C++
    Réponses: 4
    Dernier message: 13/03/2008, 22h23
  4. Constructeur & Destructeur en UML
    Par fredhali2000 dans le forum UML
    Réponses: 5
    Dernier message: 31/03/2006, 19h31
  5. [D7] constructeur / destructeur
    Par raoulmania dans le forum Langage
    Réponses: 2
    Dernier message: 16/12/2005, 18h00

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