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 */