OVH Cloud OVH Cloud

un petit probleme de constante encore:-)

7 réponses
Avatar
ricky
bonjour

decidement, j ai quelques problemes a bien comprendre les constantes en cpp

voila ce que je fais grosso modo :

class Ligne
public:
static const OK=0;
void toto();
etc

vector<Ligne> toto;
Ligne ligne;

toto.push_back(ligne);

bon
si je fais :
ligne.toto() => ca marche
cout << ligne.OK => ca marche

si je fais :
vector<Ligne>::iterator ptr;

ptr->toto() => ca marche
ptr->OK => ca ne compile pas, erreur au linkage : undefined
reference !!!

la, je ne comprend pas !
quand je passe par ligne, tout fonctionne
quand je passe par l iterateur, l appel aux fonctions marche mais pas l
acces a la constante qui est bien statique pourtant !!!

j ai encore loupe quoi ce coup ci ?

@+
ricky

7 réponses

Avatar
Fabien LE LEZ
On Sun, 16 Nov 2003 00:13:37 +0100, ricky wrote:

static const OK=0;


Tu as oublié d'indiquer le type de ta constante.

ptr->OK => ca ne compile pas, erreur au linkage : undefined
reference !!!


Ça donne la même chose avec (*ptr).OK ?

Essaie avec l'écriture "canonique" des static const :

/// Machin.h

class Ligne
{
public:
static const int OK;
};


/// Machin.cpp

const int Ligne::OK= 0;

--
;-)

Avatar
ricky
bonjour

merci de ta reponse !

static const OK=0;



Tu as oublié d'indiquer le type de ta constante.


pas dans le vrai programme :-P
j ai oublie dans le message, vieille mauvaise habitude des const en C !


Ça donne la même chose avec (*ptr).OK ?


oui, j ai tente ...


Essaie avec l'écriture "canonique" des static const :



j ai essaye, cela reste coherent : cela ne marche pas snif...

je vais essayer de donner plus de renseignement, tout en simplifiant le
code :

dans ligne.h :
class Ligne
{
string _variable;
public:
static const int OK = 0;
string getNom()
{ return _variable; };
};


dans fichier.cpp :
#include "ligne.h"
Ligne ligne();
_fichierIni.push_back(ligne);
vector<Ligne>::iterator ptr;
ptr = _fichierIni.begin();

ptr->getNom() donne le bon resultat
ptr->OK pose le probleme undefined reference a la compilation

mais si je fais
ligne.getNom()
ligne.OK
tout marche :-(

@+
ricky


Avatar
Loïc Joly
ricky wrote:
je vais essayer de donner plus de renseignement, tout en simplifiant le
code :

dans ligne.h :
class Ligne
{
string _variable;
public:
static const int OK = 0;
string getNom()
{ return _variable; };
};


dans fichier.cpp :
#include "ligne.h"


As tu pensé à définir ta constante dans le .cpp ?

int const Ligne::OK;

--
Loïc

Avatar
James Kanze
ricky writes:

|> decidement, j ai quelques problemes a bien comprendre les constantes
|> en cpp

|> voila ce que je fais grosso modo :

|> class Ligne
|> public:
|> static const OK=0;
|> void toto();
|> etc

|> vector<Ligne> toto;
|> Ligne ligne;

|> toto.push_back(ligne);

|> bon
|> si je fais :
|> ligne.toto() => ca marche
|> cout << ligne.OK => ca marche

|> si je fais :
|> vector<Ligne>::iterator ptr;

|> ptr->toto() => ca marche
|> ptr->OK => ca ne compile pas, erreur au linkage : undefined
|> reference !!!

|> la, je ne comprend pas !
|> quand je passe par ligne, tout fonctionne
|> quand je passe par l iterateur, l appel aux fonctions marche mais pas
|> l acces a la constante qui est bien statique pourtant !!!

|> j ai encore loupe quoi ce coup ci ?

Plus ou moins, mais le point est subtile.

En gros, la ligne :

static int const OK = 0 ;

dans ta définition de la classe est une declaration, non une
définition. Elle dit qu'il y aura une variable Ligne::OK. Elle
n'alloue pas la variable. Il te faut aussi, dans une seule module, une
définition :

int const Ligne::OK ;

pour dire au compilateur d'allouer la variable.

Allouée ou non, le compilateur connaît la valeur de la variable.
Il est donc possible que quand j'écris : ligne.OK, il se sert
directement de cette valeur, sans passer par la variable, et qu'il ne
génère pas d'entrée dans le fichier d'objet qui exige
l'existence de cette variable. Possible, mais pas du tout exigé ;
moi, j'ai l'erreur à l'édition de liens déjà avec ligne.OK.

Maintenant, j'avoue ne pas comprendre pourquoi le compilateur fait
différemment dans le cas d'un itérateur. À la fin, même s'il
doit évaluer l'expression ptr-> (et appeler donc
std::vector<Ligne>::iterator::operator->), il doit en ignorer le
resultat, et se servir simplement de son type ; par la suite, je ne vois
pas où il y aurait une différence. Mais bizarre ou non, il est
dans ses droits -- si tu ne fournis pas la définition (ou si tu la
fournis plus d'une fois), c'est un comportement indéfini.

--
James Kanze mailto:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France +33 1 41 89 80 93
Avatar
ricky
bonjour

As tu pensé à définir ta constante dans le .cpp ?

int const Ligne::OK;


merci a vous deux (avec james)!

effectivement, je n'avais pas vu l'interet de cette ligne, d'autant que
cela marchait bien quand je passait directement par l'objet...

cette subtilite m'avait completement echappe, mais j'ai compris la lecon
:-)

cordialement
ricky

Avatar
ricky
bonjour

Plus ou moins, mais le point est subtile.

En gros, la ligne :

static int const OK = 0 ;

dans ta définition de la classe est une declaration, non une
définition.


oui en effet !

Elle dit qu'il y aura une variable Ligne::OK. Elle
n'alloue pas la variable.


je pensait que la declaration avec le " = 0 " permettait au compilateur
de se debrouiller avec une constante (statique qui plus est) ...


Il te faut aussi, dans une seule module, une
définition :

int const Ligne::OK ;

pour dire au compilateur d'allouer la variable.


oui cela a marche en effet ... logique avec ton explication !

Allouée ou non, le compilateur connaît la valeur de la variable.


oui, c est pour cela que je pensais que cela suffisait pour une
constante !!! on a sa declaration, et la valeur qu'elle sera censee
avoir une fois pour toute !

Il est donc possible que quand j'écris : ligne.OK, il se sert
directement de cette valeur, sans passer par la variable, et qu'il ne
génère pas d'entrée dans le fichier d'objet qui exige
l'existence de cette variable. Possible, mais pas du tout exigé ;


oui j'ai constate !

moi, j'ai l'erreur à l'édition de liens déjà avec ligne.OK.


j'aurais prefere, je me serais pose moins de question.. surtout que,
honte a moi, pour les constantes, j'ai toujours fait comme cela !

std::vector<Ligne>::iterator::operator->), il doit en ignorer le
resultat, et se servir simplement de son type ; par la suite, je ne vois
pas où il y aurait une différence.


peut etre que "ignorer le resultat" n'empeche pas quand meme de lever
une erreur au moment ou il le genere, meme s'il ne l'utilise pas...

Mais bizarre ou non, il est
dans ses droits --


pffff ces compilos :-) et l'esprit du droit alors :-)
apres tout, pour une constante, donner son nom et sa valeur, cela
devrait suffir !

si tu ne fournis pas la définition (ou si tu la
fournis plus d'une fois), c'est un comportement indéfini.


bien compris

merci pour toutes ces explications

cordialement
ricky

Avatar
dpr
bonjour

decidement, j ai quelques problemes a bien comprendre les constantes en cpp

voila ce que je fais grosso modo :

class Ligne
public:
static const OK=0;
void toto();
etc

vector<Ligne> toto;
Ligne ligne;

toto.push_back(ligne);

bon
si je fais :
ligne.toto() => ca marche
cout << ligne.OK => ca marche

si je fais :
vector<Ligne>::iterator ptr;

ptr->toto() => ca marche
ptr->OK => ca ne compile pas, erreur au linkage : undefined
reference !!!

la, je ne comprend pas !
quand je passe par ligne, tout fonctionne
quand je passe par l iterateur, l appel aux fonctions marche mais pas l
acces a la constante qui est bien statique pourtant !!!

j ai encore loupe quoi ce coup ci ?

@+
ricky

Il n'y a qu'une seule valeur pour OK (car statique) pour toute les

instances de la classe Ligne. C'est pkoi c mieux et plus logique
d'utiliser "Ligne::OK" plutot que "uneLigne.OK".