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 :

Fonction inline explicite : Erreur éditions liens. Fonction inline implicite : ok! Pourquoi?


Sujet :

C++

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France, Aube (Champagne Ardenne)

    Informations forums :
    Inscription : Octobre 2009
    Messages : 15
    Points : 45
    Points
    45
    Par défaut [Résolu] Fonction inline explicite : Erreur éditions liens. Fonction inline implicite : ok! Pourquoi?
    Bonjour,

    J'ai fait face à un problème étrange pour une des fonctions membres "getParam()" d'une classe "figure".

    Ne faisant qu'une ligne, j'ai voulu la définir de façon explicite en utilisant le mot-clef inline, comme d'autres fonctions membres similaires de la classe :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    inline int figure::getParam(void) { return param; }
    g++ me fournit alors l'erreur suivante lors de l'édition des liens :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    geom_glut.o: In function `ProcessSelection(int, unsigned int, unsigned int*)':
    geom_glut.cpp:(.text+0xc9d): undefined reference to `figure::getParam()'
    collect2: ld returned 1 exit status
    Alors que tout fonctionne très bien pour d'autres fonction membres de ma classe...

    J'ai alors eu l'idée de la définir de façon explicite dans le fichier d'en-tête figure.h :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int getParam(void) { return param; };
    Et surprise cela fonctionne...

    Je suis désespérament à la recherche d'une explication rationnelle! Merci d'avance si vous pouvez m'aider.

    Ci-dessous, ma classe :
    • figure.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
      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
      #ifndef GEOM_CLASS_H
      #define GEOM_CLASS_H
       
       
      #include <list>
       
       
      /****** Structure color ******/
       
       
      struct color
      {
      	float c[3];
      	void use(void) const;
      };
       
       
      /****** classe figure ******/
       
       
      class figure
      {
      protected :
      	std::list< figure* > parents;		/* Objets dont dépend la figure */
      	std::list< figure* > children;	/* Objets dépendant de la figure */
       
      	bool locked;			/* Vérouillé? */
      	bool defined;			/* Défini? */
       
      	int col;				/* Indice couleur */
      	float width;		/* Épaisseur tracé */
       
      	int type;			/* Type de figure (ex : POINT, LINE etc...) */
      	int param;			/* Paramètres définissant la figure (ex : POINT_LINE) */
       
      	int time;			/* Quand l'objet a été crée */
      	static int clock;	/* pour savoir quand les objets sont crées les uns par rapport aux autres */
      public :
      	figure(int p);
       
      	bool getLocked(void);
      	void changeLocked(void);
       
      	bool getDefined(void);
      	void setDefined(bool b);
       
      	int getColor(void);
      	void setColor(int n);
       
      	int getType(void);
      	int getParam(void) { return param; };
       
      	void Delete(std::list< figure* >& l);	/* Liste les objets à détruire si this l'est */
       
      	virtual int Add(figure* fig){};			/* Ajoute un objet parent et renvoie true si la construction de l'objet est finie */
      	virtual void Update(void);					/* Mets à jour les pptés de l'objet et les dépendances */
       
      	virtual void Draw(void){};							/* Trace la figure */
      	virtual void Preview(float& x, float& y){};	/* Trace une figure en cours de création */
       
      	virtual bool getPoint(float& a, float& b){};	/* Obtient les coordonnées de this */
      };
       
       
      /****** classe point ******/
       
       
      class point : public figure
      {
      protected :
      	float px;
      	float py;
      //	char label;
      public :
      	point(float x, float y);
      	point(int p);
       
      	virtual int Add(figure* fig);
      	virtual void Update(void);
       
      	virtual void Draw(void);
      	virtual void Preview(float& x, float& y);
       
      	virtual bool getPoint(float& x, float& y);
      };
       
      /****** classe line ******/
      /*
      class line : public figure
      {
      public :
      	line();
      	virtual void Update(){};
      	virtual void Draw(){}; 
      };
      */
      /****** classe circle ******/
      /*
      class circle : public figure
      {
      public :
      	circle();
      	virtual void Update(){};
      	virtual void Draw(){};
      };
      */
      /****** classe tri ******/
      /*
      class tri : public figure
      {
      public :
      	tri();
      	virtual void Update(){};
      	virtual void Draw(){};
      };
      */
      /****** classe quad ******/
      /*
      class quad : public figure
      {
      public :
      	quad();
      	virtual void Update(){};
      	virtual void Draw(){};
      };
      */
      /****** classe polygon ******/
      /*
      class polygon : public figure
      {
      public :
      	polygon();
      	virtual void Update(){};
      	virtual void Draw(){};
      };
      */
       
       
      #endif /* GEOM_CLASS_H */
    • geom_class.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
      #include <iostream>
       
      #include "geom_main.h"
      using namespace std;
       
      /****** Structure color ******/
       
      void color::use(void) const
      {
      	glColor3fv(c);  
      }
       
      /****** classe figure ******/
       
      int figure::clock = 0;
       
      figure::figure(int p)
      {
      	locked = false;
      	defined = true;
      	col = WHITE;
      	param = p;
      	width = 1.;
      	time = clock++;
      }
       
      inline bool figure::getLocked(void) 	{ return locked; }
       
      inline void figure::changeLocked(void) { locked = !locked; }
       
      inline bool figure::getDefined(void) 	{ return defined; }
       
      inline void figure::setDefined(bool b) { defined = b; }
       
      inline int figure::getColor(void) 		{ return col; }
       
      inline void figure::setColor(int n)		{ col = n; }
       
      inline int figure::getType(void)			{ return type; }
       
      void figure::Update()
      {
      	defined = true;
      	/* Si un des objets dont dépend this n'est pas défini c'est inutile */
      	list< figure* >::iterator i;
      	for (i = parents.begin(); i!=parents.end(); i++)
      	{
      		if ( !( (*i) -> getDefined() ) )
      		{
      			defined = false;
      			return;
      		}
      	}
      }
       
      void figure::Delete(list< figure* >& l)
      {
      	list< figure* >::iterator i;
      	/* Ajoute les points spécialement crée lors de la création de this */
      	for (i = parents.begin(); i != parents.end(); i++)
      	{
      		if ( ((*i) -> time) > time )
      		{
      			l.push_back(*i);
      		}
      	}
      	/* Recommence l'opération pour tous les descendants de this */
      	for (i = children.begin(); i != children.end(); i++)
      	{
      		(*i) -> Delete(l);
      	}
      }
       
       
       
      /****** classe point ******/
       
       
      point::point(float x, float y) : figure(POINTPOINT_POINT)
      {
      	width = 2.0;
      	type = POINT;
      	px = x; py = y;
      }
       
      point::point(int p) : figure(p)
      {
      	width = 2.0;
      	type = POINT;
      }
       
      int point::Add(figure* fig)
      {
      	switch (param)
      	{
      		case POINTPOINT_POINT :
      			if ( (fig -> getType()) != POINT )	return NOTADDED;
      			fig -> getPoint(px, py);
      			return DONE;
      			break;
       
      		case POINTMIDDLE_POINT_POINT :
      			if ( (fig -> getType()) != POINT )	return NOTADDED;
      			parents.push_back(fig);
      			if ( parents.size() == 2)
      			{
      				Update();
      				return DONE;
      			}
      			else return ADDED;
      			break;
      	}
      }
       
      void point::Update(void)
      {
      	figure::Update();
       
      	list< figure* >::iterator i;
      	float x1, y1, x2, y2;
       
      	switch (param)
      	{
      		case POINTPOINT_POINT :
      			break;
       
      		case POINTMIDDLE_POINT_POINT :
      			parents.front() -> getPoint(x1, y1);
      			parents.back() -> getPoint(x2, y2);
      			px = x1/2. + x2/2.;
      			py = y1/2. + y2/2.;
      			break;
       
      //		case POINTMIDDLE_SEGMENT :
      //			break;
      	}
       
      	/* Application des changements aux objets dépendant de *this */
      	for (i = children.begin(); i!=children.end(); i++)
      	{
      		(*i) -> Update();
      	}
      }
       
      void point::Draw(void)
      {
      	if (!defined)	return;
      	glPointSize(width);
      	colormap[col].use();
      	glBegin(GL_POINTS);
      		glVertex2f(px,py);
      	glEnd();
      }
       
      void point::Preview(float& x, float& y)
      {
      	switch (param)
      	{
      		case POINTMIDDLE_POINT_POINT :
      			if (parents.empty())	return;
      			point p(x,y);
      			parents.push_back(&p);
      			Update();
      			Draw();
      			defined = false;
      			parents.pop_back();
      			break;
      	}
      }
       
      bool point::getPoint(float& x, float& y)
      {
      	x = px; y = py;
      	return defined;
      }
    • et le header geom_main.h qui contient les enum nécessaires :
      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
      #ifndef GEOM_MAIN_H
      #define GEOM_MAIN_H
       
       
      /****** Headers ******/
       
       
      #include <GL/glui.h>
      #include <GL/freeglut.h>
      #include <GL/glu.h>
      #include <GL/gl.h>
       
      #include "geom_class.h"
       
       
      /****** Constantes ******/
       
       
      extern const float M;	/* Dimension zone de dessin carrée */
      extern const int BORD;	/* Largeur des bords de la fenêtre pour déplacement */
       
      extern const char *obj_name[6];	/* Noms figures (Point, ...) */
       
      enum
      {
      	/* figures */  
      	POINT = 0,
      	LINE,
      	CIRCLE,
      	TRI,
      	QUAD,
      	POLYGON,
      	NONE
      };
       
      enum /* Bouttons souris */
      {
      	MOUSE_LEFT_BUTTON = 0,
      	MOUSE_MIDDLE_BUTTON = 1,
      	MOUSE_RIGHT_BUTTON = 2,
      	MOUSE_SCROLL_UP = 3,
      	MOUSE_SCROLL_DOWN = 4
      };
       
      enum /* Position souris par rapport à fenêtre */
      {
      	MOUSE_OUTSIDE = 0,
      	MOUSE_INSIDE = 1,
      	MOUSE_JUSTINSIDE = 2 	/* Pour prévenir un conflit avec glui */
      };
       
      enum /* Réponse possible lors de l'ajout d'une figure lors de la construction d'un objet */
      {
      	NOTADDED = 0,
      	ADDED = 1,
      	DONE = 2
      };
       
      enum /* Menu Principal */
      {
      	/* Modes */
      	RADIOBUTTON_MODE_EDIT = 0,
      	RADIOBUTTON_MODE_DRAW = 1,
       
      	/* Boutons*/
      	BUTTON_MOVEORIGIN,
      	BUTTON_RESETZOOM,
      	RADIOBUTTON_MODE,
      	LISTBOX_OBJ,
      	BUTTON_CLEAR,
      	BUTTON_QUIT
      };
       
      enum /* Menu Point */
      {	
      	/* Types */
      	POINTPOINT_POINT,
      	POINTMIDDLE_POINT_POINT,
      	POINTMIDDLE_SEGMENT,
      	POINTINTERSECTION,
       
      	/* Boutons */
      	POINT_PROPERTIES_LOCKED,
      	POINT_PROPERTIES_LABEL,
      	POINT_PROPERTIES_DELETE
      };
       
      /* Couleurs */
       
      const color black = {0.0, 0.0, 0.0}, red = {1.0, 0.0, 0.0}, green = {0.0, 1.0, 0.0},
      		blue = {0.0, 0.0, 1.0}, cyan = {0.0, 1.0, 1.0}, yellow = {1.0, 1.0, 0.0},
      		magenta = {1.0, 0.0, 1.0}, white = {1.0, 1.0, 1.0};
       
      const color colormap[8] = {black, red, green, blue, cyan, yellow, magenta, white};
       
      enum 
      {
      	BLACK = 0,
      	RED,
      	GREEN,
      	BLUE,
      	CYAN,
      	YELLOW,
      	MAGENTA,
      	WHITE
      };
       
       
      /****** Variables Globales ******/
       
       
      /* Fenêtre Graphique */
      extern float X, Y;			/* Coordonnées coin gauche fenêtre */
      extern float lX, lY;			/* Dimensions fenêtre */
      extern int Xview, Yview;	/* Dimensions viewport */
      extern int win_main;			/* ID Fenêtre graphique */
       
      /* Dessin */
      extern std::list< figure* > figures;	/* Figures du dessin */
      extern figure* newobj;						/* Figure courante */
       
      /* Souris */
      extern int xold, yold;	/* Coordonnées souris */
      extern int move;			/* Déplacement centre fenêtre */
      extern int mouse;			/* Souris dans fenêtre? */
       
      /* Elements Menu */
      extern GLUI* glui_main;					/* Menu principal */
      extern GLUI* glui_edit[6];				/* Menus édition */
      extern GLUI_Listbox* listbox_obj;	/* Choix figure */
       
      extern GLUI_Panel* panel_type[6];
      extern GLUI_Panel* panel_properties[6];
      extern GLUI_Listbox* listbox_type[6];
       
      /* Menu : Live Variables */
      extern int menu_view_axis;
      extern int menu_view_square;
      extern int menu_view_coord;
      extern int menu_mode;				/* Mode : Edit ou Draw */
      extern int menu_obj;					/* Figure courante */
      extern int menu_obj_old;			/* Précédente figure courante */
      extern int obj_type;					/* Objet courant */
       
       
      /****** Fonctions geom_glut.cpp ******/
       
      /*** Affichage ***/
       
      /* Freeglut Callback functions */
      void Reshape(int width, int height);
      void Display(void);
       
      /* Gestion zoom & déplacements */
      void Zoom(float a, float x, float y);
      void TestPosition(void);	/* Si la zone d'affichage est bien dans la zone de dessin */
       
      /*** Souris ***/
       
      /* Freeglut Callback functions */
      void Mouse(int button, int state, int x, int y);
      void Motion(int x, int y);
      void PassiveMotion(int x, int y);
      void TestMouse(int state);		/* Si la souris sors de la fenêtre */
      void TestBords();					/* Si la souris est proche du bord de la fenêtre */
       
      /* Conversions entre coordonnées souris et coordonnées réelles */
      void Mouse2Coord(float & x, float & y);
      void Coord2Mouse(float & x, float & y);
       
      /* Sélection */
      void ProcessSelection(int n, GLuint p, GLuint * selectBuf);
       
      /*** Clavier ***/
       
      /* Freeglut Callback functions */
      void KeyboardNormalKeys(unsigned char key, int x, int y);
      void KeyboardSplecialKeys(int key, int x, int y);
       
       
      /****** Fonctions geom_menu.cpp ******/
       
      /* Menu Principal */
      void MainCreateMenu(void);
      void MainProcessMenu(int n);
       
      /* Menus d'édition */
      void CreateEditMenu(void);
      void InitEditMenu(void);
      void ProcessEditMenu(int n);
       
      void CreateNewFigure(void);
      void CancelNewFigure(void);
       
       
      #endif /* GEOM_MAIN_H */

  2. #2
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France, Aube (Champagne Ardenne)

    Informations forums :
    Inscription : Octobre 2009
    Messages : 15
    Points : 45
    Points
    45
    Par défaut
    Je viens de découvrir que les fonctions membres suivantes de la classe figure posent aussi problème :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    inline bool figure::getLocked(void) { return locked; }
     
    inline void figure::changeLocked(void) { locked = !locked; }
    Ce n'est sûrement donc pas un hasard si cela ne fonctionne pas... Ce qui me chagrine c'est que la fonction suivante ne pose par contre pas de problème :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    inline int figure::getType(void) { return type; }

  3. #3
    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
    Salut,
    F.A.Q. : Comment signaler au compilateur de mettre une fonction membre inline ?
    Il est habituellement impératif que la définition de la fonction (la partie entre {... }) soit placée dans un fichier d'en-tête. Si vous mettiez inline la définition d'une fonction dans un fichier d'implémentation cpp, et si cette fonction était appelée d'un autre fichier cpp, vous obtiendriez "une erreur externe" (fonction non définie) au moment de l'édition de liens.
    Il faut donc que tu mettes tes fonctions inline dans ton .h

    P.S. : au passage :
    -> tes fonctions ne sont pas const-correct,
    -> si tu as des get et des set sur tes attributs, alors autant les passer public non ? Car je ne vois plus l'intérêt de les avoir privés.

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France, Aube (Champagne Ardenne)

    Informations forums :
    Inscription : Octobre 2009
    Messages : 15
    Points : 45
    Points
    45
    Par défaut
    J'avoue que je pensais pas que la FAQ était aussi complète. L'obligation de définir les fonctions inline dans le fichier d'en-tête n'était pas précisée dans le livre sur lequel j'ai appris le c++.

    Tu avais raisons, j'ai passé mes attributs en public et viré les accesseurs/mutateurs inutiles... J'ai voulu faire trop compliqué! C'est beaucoup plus claire maintenant.

    Je vais essayer de rendre mes fonctions "const-correct" le plus vite possible. Honnêtement je ne savais pas ce que ça voulait dire mais ce lien m'a beaucoup aidé.

    Merci beaucoup pour ta réponse en tout cas!

Discussions similaires

  1. [Débutant] erreur W8027 Les fonctions contenant switch ne sont pas développées inline
    Par microbe83 dans le forum C++Builder
    Réponses: 1
    Dernier message: 23/04/2013, 18h09
  2. Réponses: 8
    Dernier message: 21/04/2011, 10h58
  3. Réponses: 6
    Dernier message: 08/12/2007, 14h33
  4. Réponses: 11
    Dernier message: 20/01/2006, 12h35
  5. Erreur sur une fonction avec des paramètres
    Par Elois dans le forum PostgreSQL
    Réponses: 2
    Dernier message: 05/05/2004, 21h00

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