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++Builder Discussion :

TADOConnection + Unresolved external


Sujet :

C++Builder

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Septembre 2009
    Messages
    65
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2009
    Messages : 65
    Par défaut TADOConnection + Unresolved external
    Bonjour,

    Je travaille actuellement sous C++ Builder 5 et essaie d'implémenter une classe qui me permettra de me connecter à différentes bases de données pour les besoin de l'application que je réalise.
    J'ai fait le choix d'une classe statique, à savoir que l'ensemble des attributs et méthodes sont statiques.

    Mon premier problème est que j'obtiens les messages suivants à la compilation :
    [Lieur Erreur] Unresolved external 'Database::cnnSQLBIF' referenced from C:\PROGRAM FILES\BORLAND\CBUILDER5\PROJECTS\DATABASE.OBJ
    [Lieur Erreur] Unresolved external 'Database::cnnSQLData' referenced from C:\PROGRAM FILES\BORLAND\CBUILDER5\PROJECTS\DATABASE.OBJ
    J'ai vérifié plusieurs fois si je n'avais pas oublié un petit quelque chose et, à première vue, il me semble que non.

    Mon deuxième problème est le fait que lorsque je veux instancier mon objet TADOConnection, je suis censé faire :
    cnnMDB = new TADOConnection(this);
    J'obtiens alors le message suivant :
    [C++ Erreur] Database.cpp(23): E2297 'this' ne peut être utilisé que dans une fonction membre
    Je comprends pourquoi le compilateur me signale cette erreur (c'est logique, vu que c'est du statique, le pointeur this ne fait référence à rien), je ne peux donc pas faire ça.
    Mais alors, comment dois-je procéder ? Suis-je obligé de faire de cette façon ? Y a-t-il une alternative ?

    Voici le code pour mieux comprendre et visualiser :

    Database.h :
    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
     
    #ifndef DatabaseH
    #define DatabaseH
     
    #include <ADODB.hpp>
     
    class Database
    {
       private:
            static TADOConnection *cnnMDB;
            static TADOConnection *cnnSQLBIF;
            static TADOConnection *cnnSQLData;
       public:
            static bool __fastcall openMDBConnection(String dbName);
            static bool __fastcall openSQLConnection(bool bForBif, String userName, String pw, String serverNamedPipe, String serverAddress, String serverCustom, String dbName);
            static bool __fastcall openSQLConnections(String userName, String pw, String serverNamedPipe, String serverAddress, String serverCustom, String BIFDBName, String DataDBName);
     
    };
    #endif
    Database.cpp :
    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
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
     
    #include <vcl.h>
    #pragma hdrstop
     
    #include "Database.h"
     
    bool __fastcall Database::openMDBConnection(String dbName)
    {
       String cs = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + dbName;
       // voir message compilo quand commentaire retiré
       //cnnMDB = new TADOConnection(this);
       Database::cnnMDB->CursorLocation = clUseClient;
       Database::cnnMDB->ConnectionString = cs;
       Database::cnnMDB->LoginPrompt = false;
       try { Database::cnnMDB->Connected = true; }
       catch (EADOError *e) { return false; }
     
       return true;
    }
     
    bool __fastcall Database::openSQLConnection(bool bForBif, String userName, String pw, String serverNamedPipe, String serverAddress, String serverCustom, String dbName)
    {
       String cs = "Provider=SQLOLEDB.1;Password=" + pw + ";Persist Security Info=True;" + "User ID=" + userName + ";Initial Catalog=" + dbName;
     
       if(serverNamedPipe != "")
            cs += ";Data Source=" + serverNamedPipe;
       else
            cs += ";Network Address=" + serverAddress + ";Network Library=dbmssocn";
     
       if(serverCustom != "")
       {
            cs = serverCustom;
            cs = StringReplace(cs, "<PW>", pw, TReplaceFlags());
            cs = StringReplace(cs, "<ID>", userName, TReplaceFlags());
            cs = StringReplace(cs, "<DB>", dbName, TReplaceFlags());
       }
     
       if(bForBif)
       {
            // voir message compilo quand commentaire retiré
            //cnnSQLBIF = new TADOConnection(this);
            Database::cnnSQLBIF->CursorLocation = clUseClient;
            Database::cnnSQLBIF->ConnectionString = cs;
            Database::cnnSQLBIF->LoginPrompt = false;
            try { Database::cnnSQLBIF->Open(userName, pw); }
            catch (EADOError *e) { return false; }
     
            return true;
       }
       else
       {
            // voir message compilo quand commentaire retiré
            //cnnSQLData = new TADOConnection(this);
            Database::cnnSQLData->CursorLocation = clUseClient;
            Database::cnnSQLData->ConnectionString = cs;
            Database::cnnSQLData->LoginPrompt = false;
            try { Database::cnnSQLData->Open(userName, pw); }
            catch (EADOError *e) { return false; }
     
            return true;
       }
    }
     
    bool __fastcall Database::openSQLConnections(String userName, String pw, String serverNamedPipe, String serverAddress, String serverCustom, String BIFDBName, String DataDBName)
    {
       bool rc;
     
       rc = openSQLConnection(true, userName, pw, serverNamedPipe, serverAddress, serverCustom, BIFDBName);
       if(rc)
       {
            rc = openSQLConnection(false, userName, pw, serverNamedPipe, serverAddress, serverCustom, DataDBName);
            if(!rc)
                    Database::cnnSQLBIF->Close();
       }
     
       return rc;
    }
     
    #pragma package(smart_init)
    J'ai également une autre question :

    Comment accéder à des composants de ma GUI depuis une autre classe, composants déclarés dans la partie __published du .h ?

    Merci d'avance.

  2. #2
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 086
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 086
    Par défaut
    les membres statiques nécessitent un emplacement de stockage a mettre dans le .H et le CPP selon ta préférence

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    TADOConnection* Database::cnnMDB = NULL;
    TADOConnection* Database::cnnSQLBIF = NULL;
    TADOConnection* Database::cnnSQLData = NULL;
    Pourquoi utilises-tu du static ?
    Si tu fais un objet C++ standard, comme c'est le cas, tu peux juste créer une variable globale en allocation statique qui te servira de singleton !
    Tu pourras avoir des membres d'instance, c'est plus simple non que de créer toutes la classe en static !


    Tu dois mettre NULL comme Onwer,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
       cnnMDB = new TADOConnection(NULL);
    si il se montre capricieux, cela arrive
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
       cnnMDB = new TADOConnection((TComponent*)NULL);
    Ne pas oublier de faire autant de delete que new dans ta future fonction closeMDBConnection

    Plusieurs questions, dans le même sujet, ce n'est pas conforme au règles du forum, passons ...

    Si tu veux utiliser les membres d'une classe dans le fichier d'une autre classe, tu dois inclure le .h utilisé dans le fichier .CPP qui l'utilisera !
    C'est la base de l'include !



    Avant d'aller plus loin, il te faudrait revoir les Bases du C++ et C++Builder !
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  3. #3
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Septembre 2009
    Messages
    65
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2009
    Messages : 65
    Par défaut
    Tout d'abord merci d'avoir répondu.
    Et un merci de plus car tes conseils quant à mon problème de TADOConnection ont porté leurs fruits, ça marche maintenant magnifiquement bien !

    En ce qui concerne l'utilisation des membres de mon autre classe, j'avais déjà essayé d'inclure le .h, sans succès (suis quand même pas aussi débutant que ça ^^). Voici le code :

    Gui.h :
    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
     
    #ifndef GuiH
    #define GuiH
     
    #include <Classes.hpp>
    #include <Controls.hpp>
    #include <StdCtrls.hpp>
    #include <Forms.hpp>
    #include <ComCtrls.hpp>
    #include <Dialogs.hpp>
    #include <ADODB.hpp>
    #include <Db.hpp>
     
    class TInterface : public TForm
    {
    __published:	// Composants gérés par l'EDI
            TLabel *userNameLabel;
    private:	// Déclarations utilisateur
    public:	// Déclarations utilisateur
            __fastcall TInterface(TComponent* Owner);
    };
     
    extern PACKAGE TInterface *Interface;
     
    #endif
    CmdLine.cpp (là où je voudrais pouvoir avoir accès au TLabel) :
    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
     
    #include <vcl.h>
    #pragma hdrstop
     
    #include <IniFiles.hpp>
    #include "CmdLine.h"
    #include "Gui.h"
     
    void __fastcall CmdLine::readSettings()
    {
       String path = ExtractFilePath(Application->ExeName)+"settings.ini";
       TIniFile *settings = new TIniFile(path);
     
       if(settings->SectionExists("init"))
       {
            userNameEdit->Text = settings->ReadString("init", "username", "def");
       }
    }
     
    #pragma package(smart_init)
    Le message d'erreur :
    [C++ Erreur] CmdLine.cpp(16): E2451 Symbole 'userNameEdit' non défini

    Merci d'avance.

  4. #4
    Membre Expert
    Avatar de DjmSoftware
    Homme Profil pro
    Responsable de compte
    Inscrit en
    Mars 2002
    Messages
    1 044
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Responsable de compte
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 044
    Billets dans le blog
    1
    Par défaut
    Salut
    en principe cela devrait être
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Interface->userNameLabel=settings->ReadString("init", "username", "def");
    cdlt
    vous trouverez mes tutoriels à l'adresse suivante: http://djmsoftware.developpez.com/
    je vous en souhaite une excellente lecture ...

    A lire : Les règles du forum

  5. #5
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Septembre 2009
    Messages
    65
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2009
    Messages : 65
    Par défaut
    Citation Envoyé par DjmSoftware Voir le message
    Salut
    en principe cela devrait être
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Interface->userNameLabel=settings->ReadString("init", "username", "def");
    cdlt
    Effectivement, cela marche maintenant correctement, merci à toi !


    ShaiLeTroll :
    Quand tu dis :
    "Pourquoi utilises-tu du static ?
    Si tu fais un objet C++ standard, comme c'est le cas, tu peux juste créer une variable globale en allocation statique qui te servira de singleton !
    Tu pourras avoir des membres d'instance, c'est plus simple non que de créer toutes la classe en static !"


    Tu me conseilles d'utiliser le patron de conception singleton en gros ? J'y avais déjà pensé mais l'idée de faire des classes statiques m'a semblé plus facile au premier abord. Je sais bien que ce n'est pas une "bonne pratique" mais disons que le programme sur lequel je travaille n'a pas vraiment été pensé objet mais plutôt procédural (je dois en fait ré-écrire et optimiser un programme écrit en VB6 à la base). Quels seraient les avantages à ta proposition ? Je ne suis pas si expérimenté que ça, toute idée est bonne à prendre et à creuser.

  6. #6
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 086
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 086
    Par défaut
    En fait, static, ça te fait faire plus de code !

    tu pouvais faire ceci

    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
    class CDatabase
    {
       private:
            TADOConnection *cnnMDB;
            TADOConnection *cnnSQLBIF;
            TADOConnection *cnnSQLData;
       public:
            CDatabase();
            ~CDatabase();
            bool __fastcall openMDBConnection(String dbName);
            bool __fastcall openSQLConnection(bool bForBif, String userName, String pw, String serverNamedPipe, String serverAddress, String serverCustom, String dbName);
            bool __fastcall openSQLConnections(String userName, String pw, String serverNamedPipe, String serverAddress, String serverCustom, String BIFDBName, String DataDBName);
    };
     
    extern CDatabase MyDatabase;
    dans le CPP, tu une seule variable globale !

    tu peux ainsi utiliser le this au besoin, ça te fait moins de mot clé, en plus, je trouve l'appel est plus "lisible"
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    CDatabase::openMDBConnection(...);
    devient
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    MyDatabase.openMDBConnection(...);
    et le couple constructeur\destructeur
    tu n'as pas besoin d'y pense avec une variable en allocation statique, le destructeur sera appelé automatiquement et libérera tes objets internes !

    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
     
    CDatabase::~CDatabase()
    {
      cnnMDB = NULL;
      cnnSQLBIF = NULL;
      cnnSQLData = NULL;
    }
     
    CDatabase::~CDatabase()
    {
      delete cnnMDB;
      cnnMDB = NULL;
     
      delete cnnMDB;
      cnnSQLBIF = NULL;
     
      delete cnnMDB;
      cnnSQLData = NULL;
    }
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

Discussions similaires

  1. TADOConnection + Unresolved external
    Par Tenebrous dans le forum C++
    Réponses: 1
    Dernier message: 15/02/2012, 10h24
  2. unresolved external symbol _IID_IDi
    Par PC23 dans le forum DirectX
    Réponses: 6
    Dernier message: 05/08/2005, 10h38
  3. PB de buil : unresolved external symbol
    Par dede92 dans le forum Windows
    Réponses: 8
    Dernier message: 13/12/2004, 11h21
  4. unresolved external symbol _IID_IDirectDraw7
    Par lvdnono dans le forum DirectX
    Réponses: 2
    Dernier message: 15/06/2004, 21h05
  5. Réponses: 4
    Dernier message: 23/04/2004, 16h06

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