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 :

exporter une classe + surcharge de l'opérateur <<


Sujet :

C++

  1. #1
    Membre éprouvé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 299
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 299
    Par défaut exporter une classe + surcharge de l'opérateur <<
    Bonjour, je me mets au C++ (après avoir bcp fait de C). J'arrive à exporter une classe mais j'ai un soucis dans la surcharge de l'opérateur <<.

    A l'exécution, j'obtiens l'erreur suivante :

    error LNK2019: unresolved external symbol "class std::basic_ostream<char,struct std::char_traits<char> > & __cdecl operator<<(class std::basic_ostream<char,struct std::char_traits<char> > &,class DataExpNSF const &)" (??6@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AAV01@ABVDataExpNSF@@@Z) referenced in function "void __cdecl testTSSNSF(char const *,struct _iobuf *)" (?testTSSNSF@@YAXPBDPAU_iobuf@@@Z)
    Voici mon code :

    qq macros (chopée du net) :

    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
     
    /* macro pour exporter (importer) un std::vector dans une (d'une) dll */
    #define IMPORTEXPORT_STL_VECTOR( dllmacro, vectype ) \
      template class dllmacro std::allocator< vectype >; \
      template class dllmacro std::vector<vectype, \
        std::allocator< vectype > >
     
    /* macro pour exporter un std::vector dans une dll */
    #define EXPORT_STL_VECTOR( vectype ) IMPORTEXPORT_STL_VECTOR(__declspec(dllexport), vectype )
     
    /* macro pour importer un std::vector d'une dll */
    #define IMPORT_STL_VECTOR( vectype ) IMPORTEXPORT_STL_VECTOR(__declspec(dllimport), vectype )
     
    /* macro pour exporter un std::vector<double> dans une dll */
    #define EXPORT_STL_VECTOR_DOUBLE EXPORT_STL_VECTOR(double)
     
    #ifdef BIBStructures_EXPORTS
    #define BIBStructures_API __declspec(dllexport)
    #else
    #define BIBStructures_API __declspec(dllimport)
    #endif
    Mon .hpp

    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
     
    EXPORT_STL_VECTOR_DOUBLE;
     
    class BIBStructures_API DataExpNSF
    {
      private :
     
        int               _titre;    /* titre de l'eprouvette */
    	double            _pretens;  /* pretension [N]        */
    	vector < double > _t;        /* temps [s]             */
    	vector < double > _traverse; /* traverse normee [mm]  */
    	vector < double > _F;        /* force standard [N]    */
    	vector < double > _allong;   /* allongement [%]       */
    	vector < double > _T;        /* temperature [deg C]   */
     
      public :
     
      /* default constructor */
      DataExpNSF();
     
      /* constructor */
      DataExpNSF(int titre,double pretens,const vector < double > & t,const vector < double > & traverse,
    	  const vector < double > & F,const vector < double > & allong,const vector < double > & T);
     
      /* destructor */
      ~DataExpNSF();
     
      /* renvoie la valeur du titre de l'eprouvette */
      int getTitre(void) const;
     
      /* fixe la valeur du titre de l'eprouvette */
      void setTitre(int titre);
     
      /* renvoie la valeur de la pretension (en N) */
      double getPretension(void) const;
     
      /* fixe une valeur a la pretension */
      void setPretension(double pretens);
     
      /* retourne le vector contenant les temps [s] */
      const vector<double> & getTemps(void) const;
     
      /* retourne le vector contenant les traverses normees [mm] */
      const vector<double> & getTraverse(void) const;
     
      /* retourne le vector contenant les forces standard [N] */
      const vector<double> & getForce(void) const;
     
      /* retourne le vector contenant les allongements [%] */
      const vector<double> & getAllong(void) const;
     
      /* retourne le vector contenant les temperatures [deg C] */
      const vector<double> & getTemperature(void) const;
     
      /* true si les vectors _t, _traverse, _F, _allong et _T sont de meme dimension
         false sinon
       */
      bool checkDimensions(void) const;
     
      /* ajoute un element a la fin de chaque vector */
      void pushBackSample(double t,double traverse,double F,double allong,double T);
     
      /* lecture d'un fichier de mesure et stockage des donnees experimentales dans la classe DataExpNSF
     
         renvoie :
          0 : aucune erreur
         -1 : echec lors de l'ouverture du fichier de mesure
          1 : echec lors de la lecture de la valeur du titre de l'eprouvette
          2 : echec lors de la lecture de la valeur de la pretension
    	  3 : echec lors de la lecture du nom des colonnes
    	  4 : echec lors de la lecture des unites des colonnes
    	  5 : echec lors de la lecture des donnees experimentales
       */
      int readFile(const string & filename);
     
      /* surcharge de l'operateur << */
      friend std::ostream & operator<<(std::ostream & os, const DataExpNSF & d);
    };
    et voici mon .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
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
     
    /* default constructor */
    DataExpNSF::DataExpNSF()
    {
      _titre = -1; _pretens = -1.;
    }
     
    /* constructor */
    DataExpNSF::DataExpNSF(int titre, double pretens, const std::vector<double> & t, 
    					   const std::vector<double> & traverse, const std::vector<double> & F, 
    					   const std::vector<double> & allong, const std::vector<double> & T)
    {
      _titre    = titre;
      _pretens  = pretens;
      _t        = t;
      _traverse = traverse;
      _F        = F;
      _allong   = allong;
      _T        = T;
    }
     
    /* destructor */
    DataExpNSF::~DataExpNSF()
    {
      _titre = -1; _pretens = -1.;
      _t.clear(); _traverse.clear(); _F.clear(); _allong.clear(); _T.clear();
    }
     
    /* getTitre :
       renvoie la valeur du titre de l'eprouvette
     */
    inline int DataExpNSF::getTitre(void) const
    {
      return _titre;
    }
     
    /* setTitre :
       fixe la valeur du titre de l'eprouvette
     */
    inline void DataExpNSF::setTitre(int titre)
    {
      _titre = titre;
    }
     
    /* getPretension :
       renvoie la valeur de la pretension (en N)
     */
    inline double DataExpNSF::getPretension(void) const
    {
      return _pretens;
    }
     
    /* setPretension :
       fixe une valeur a la pretension
     */
    inline void DataExpNSF::setPretension(double pretens)
    {
      _pretens = pretens;
    }
     
    /* getTemps :
       retourne le vector contenant les temps [s]
     */
    inline const vector<double> & DataExpNSF::getTemps(void) const
    {
      return _t;
    }
     
    /* getTraverse :
       retourne le vector contenant les tracerses normees [mm]
     */
    inline const vector<double> & DataExpNSF::getTraverse(void) const
    {
      return _traverse;
    }
     
    /* getForce :
       retourne le vector contenant les forces standard [N]
     */
    inline const vector<double> & DataExpNSF::getForce(void) const
    {
      return _F;
    }
     
    /* getAllong :
       retourne le vector contenant les allongements [%]
     */
    inline const vector<double> & DataExpNSF::getAllong(void) const
    {
      return _allong;
    }
     
    /* getTemperature :
       retourne le vector contenant les temperatures [deg C]
     */
    inline const vector<double> & DataExpNSF::getTemperature(void) const
    {
      return _T;
    }
     
    /* checkDimensions :
       true si les vectors _t, _traverse, _F, _allong et _T sont de meme dimension
       false sinon
     */
    inline bool DataExpNSF::checkDimensions(void) const
    {
      size_t n = _t.size();
      if( (_traverse.size() == n) && (_F.size() == n) && (_allong.size() == n) && (_T.size() == n) )
        return true;
      else
        return false;
    }
     
    /* pushBackSample : 
       ajoute un element a la fin de chaque vector
     */
    void DataExpNSF::pushBackSample(double t,double traverse,double F,double allong,double T)
    {
      _t.push_back(t); _traverse.push_back(traverse); _F.push_back(F); _allong.push_back(allong);
      _T.push_back(T);
    }
     
    std::ostream & operator<<(std::ostream & os, const DataExpNSF & d)
    {
      bool test = d.checkDimensions();
      if(test == true)
      {
        const vector<double> t        = d.getTemps();
        const vector<double> traverse = d.getTraverse();
        const vector<double> F        = d.getForce();
        const vector<double> allong   = d.getAllong();
        const vector<double> T        = d.getTemperature();
    	size_t i, n = t.size();
     
        os << "titre = " << d.getTitre() << std::endl;
        os << "pretension = " << d.getPretension() << " N" << std::endl << std::endl;
        os << "1e colonne : temps [s]" << std::endl;
        os << "2e colonne : traverse normee [mm]" << std::endl;
        os << "3e colonne : force [N]" << std::endl;
        os << "4e colonne : allongement [%]" << std::endl;
        os << "5e colonne : temperature [deg C]" << std::endl << std::endl;
     
        for(i = 0 ; i < n ; i++)
    	{
          os << t[i] << ' ' << traverse[i] << ' ' << F[i] << ' ' << allong[i] << ' ' << T[i] << std::endl;
    	}
    	os << std::endl;
      }
      else /* test == false */
      {
    	std::cerr << "Erreur de dimension !!" << std::endl;
      }
     
      return os;
    }
     
    /* readFile :
       lecture d'un fichier de mesure et stockage des donnees experimentales dans la classe DataExpNSF
     
       renvoie :
        0 : aucune erreur
       -1 : echec lors de l'ouverture du fichier de mesure
        1 : echec lors de la lecture de la valeur du titre de l'eprouvette
        2 : echec lors de la lecture de la valeur de la pretension
    	3 : echec lors de la lecture du nom des colonnes
    	4 : echec lors de la lecture des unites des colonnes
    	5 : echec lors de la lecture des donnees experimentales
     */
    int DataExpNSF::readFile(const string & filename)
    {
      /* ouverture du fichier en lecture */
      std::ifstream file( filename.c_str() );
     
      if(!file) /* echec a l'ouverture */
      {
        ERRORFOPEN(filename);
    	return -1;
      }
      else
      {
        string line; /* variable contenant la ligne lue */
    	int    flag_pretens, flag_titre, flag_colname, flag_colunite, ret, flag_reading;
    	double t, traverse, F, allong, T, aux;
    	size_t len;
    	char   str[1024];
     
    	/* nom des colonnes : il y a 2 possibilites */
    	const string colname1 = "\"Temps d'essai\";\"Traverse normée\";\"Force standard\";\"Allong.\";\"Température\"";
    	const string colname2 = "Temps d'essai	Traverse normée	Force standard	Allong.	Température";
     
    	/* unite des colonnes : il y a 2 possibilites */
    	const string colunite1 = "\"s\";\"mm\";\"N\";\"%\";\"°C\"";
    	const string colunite2 = "s	mm	N	%	°C";
     
    	/* intialisation des flags */
    	flag_pretens = flag_titre = flag_colname = flag_colunite = flag_reading = 1;
     
    	while ( std::getline( file, line ) ) /* lecture du fichier */
    	{
    	  /* lecture de la valeur de la pretension */
    	  if(flag_pretens)_pretens = readPretension(flag_pretens,line);
     
    	  /* lecture du titre de l'eprouvette */
    	  if(flag_titre)_titre = readTitre(flag_titre,line);
     
    	  /* lecture du nom et des unites des colonnes. On doit d'abord avoir le nom des colonnes
    	     puis leurs unites
    	   */
    	  if(flag_colname && flag_colunite && ((line == colname1) || (line == colname2)) ) flag_colname = 0;
     
    	  if(!flag_colname && flag_colunite && ((line == colunite1) || (line == colunite2)) ) flag_colunite = 0;
     
     
    	  if( (flag_reading == 1) && !flag_colname && !flag_colunite )
    	    flag_reading = 0;
    	  else if(flag_reading == 0)
    		  flag_reading = 2;
     
    	  /* lecture des donnees experimentales */
    	  if(flag_reading == 2)
    	  {
    	    len = line.copy(str,line.size(),0);
    		str[len] = '\0';
     
    		/* on remplace tous les ';' par des ' ' et tous les ',' par des '.'*/
    		for(size_t i = 0 ; i < len ; i++)
    		{
              if(str[i] == ';')
    		    str[i] = ' ';
    		  else if(str[i] == ',')
    		    str[i] = '.';
    		}
     
    		/* on veut lire 5 colonnes. On fait expres d'en mettre 6 pour s'assurer qu'il y en
    		   a exactement 5
    	     */
    		ret = sscanf(str,"%lf%lf%lf%lf%lf%lf",&t,&traverse,&F,&allong,&T,&aux);
    		if(ret == 5)
    		{
              /* stockage des donnees experimentales */
    		  _t.push_back(t); _traverse.push_back(traverse); _F.push_back(F);
    		  _allong.push_back(allong); _T.push_back(T);
    		}
    		else
    		{
    		  ERROR("reading error");
    		  std::cerr << "ret = " << ret << std::endl;
    		  std::cerr << "line = " << line << std::endl;
    		  std::cerr << "length = " << line.size() << std::endl;
     
              return 5;
    		}
    	  } /* if(!flag_colname && !flag_colunite) */
     
    	} /* while ( std::getline( file, line ) ) */
     
    	file.close();
     
    	/* retour des erreurs de lecture */
    	if(_titre == -1) return 1;
    	if(fabs(_pretens + 1) < EPS) return 2;
    	if(flag_colname) return 3;
    	if(flag_colunite) return 4;
     
    	return 0;
     
      } /* else "if(!file)" */
    }
    En gros le problème est : comment exporter la fonction operator << ?

    Merci d'avance

  2. #2
    Membre Expert
    Avatar de coyotte507
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    1 327
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 1 327
    Par défaut
    Pour moi, si je met tout dans un même fichier et que j'enlève certains trucs que tu n'as pas fourni (ERROR, ERRORFOPEN, ...) ça compile.

  3. #3
    Membre éprouvé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 299
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 299
    Par défaut
    Citation Envoyé par coyotte507 Voir le message
    Pour moi, si je met tout dans un même fichier et que j'enlève certains trucs que tu n'as pas fourni (ERROR, ERRORFOPEN, ...) ça compile.

    Re,

    oui la génération de la dll compile. Maintenant si dans un main (pour tester la dll générée) tu fais (avec les bons include) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    DataExpNSF dataexp;
    int err = dataexp.readFile(filename);
    cout << dataexp << endl;
    là j'ai l'erreur :

    error LNK2019: unresolved external symbol "class std::basic_ostream<char,struct std::char_traits<char> > & __cdecl operator<<(class std::basic_ostream<char,struct std::char_traits<char> > &,class DataExpNSF const &)" (??6@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AAV01@ABVDataExpNSF@@@Z) referenced in function "void __cdecl testDataExpNSF(char const *,struct _iobuf *)" (?testDataExpNSF@@YAXPBDPAU_iobuf@@@Z)

  4. #4
    Membre éprouvé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 299
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 299
    Par défaut
    Je pense que l'erreur vient du fait que la fonction amie operator << ne fait pas parti de la classe (car elle est amie) et donc elle n'est pas exportée...

  5. #5
    Membre Expert
    Avatar de coyotte507
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    1 327
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 1 327
    Par défaut
    Je ne connais pas vraiment les DLL, donc d'autres seront plus habilités à te répondre (ou alors des recherches sur internet), mais:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    /* surcharge de l'operateur << */
      friend std::ostream & operator<<(std::ostream & os, const DataExpNSF & d);
    Là l'opérateur << est déclaré comme une fonction n'appartenant à aucune classe, donc l'exportation de ta classe ne s'applique pas à cette fonction.

    Ne faudrait-il pas exporter cette fonction de la même manière qu'on exporte une fonction n'appartenant à aucune classe?

    Edit: oui

  6. #6
    Membre éprouvé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 299
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 299
    Par défaut
    Citation Envoyé par coyotte507 Voir le message

    Ne faudrait-il pas exporter cette fonction de la même manière qu'on exporte une fonction n'appartenant à aucune classe?
    Re,

    si je pense que le pb vient de là. Je suis en train de voir comment exporter une fonction amie : où mettre le extern "C", le BIBStructure_API et le __stdcall

    je découvre...

Discussions similaires

  1. Exporter une classe Java sous forme d'un jar/file
    Par ebenmous dans le forum NetBeans
    Réponses: 5
    Dernier message: 09/08/2011, 09h55
  2. Réponses: 4
    Dernier message: 31/05/2009, 10h38
  3. Exporter une classe dans une DLL
    Par mayayu dans le forum C++
    Réponses: 3
    Dernier message: 29/12/2008, 11h53
  4. Exporter une class dans une DLL
    Par squale69 dans le forum C++
    Réponses: 2
    Dernier message: 25/04/2008, 17h54
  5. rendre exportable une classe
    Par FamiDoo dans le forum Visual C++
    Réponses: 4
    Dernier message: 09/08/2006, 08h53

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