[C++] Passage de référence

Passage de référence [C++] - Programmation

Marsh Posté le 04-10-2001 à 15:20:36    

G encore jammais posé de questions de C++ pur et dur ici, on va voir si y a des connaisseurs :
 
bon, voila, g crée une classe CDlgPilot.
Ailleur dans mon prog, je veux appeler une fonction globale (ouais, mon programme est une peu un mélange entre C et C++ : adatation d'un vieux truc) qui prend pour paramètre une référence de CDlgPilot. Voici la déclaration de cette fonction:
 
int IsisScan(const CClipScanPilote& _piloteDlg = NULL);
 
jusqu'a là, tout compile, mais quand j'implémente cette fonction et que j'essaye d'utiliser _piloteDlg, par exemple de cette façon:
 
_piloteDlg.IncrCompteur(); //incrCompteur étant une méthode de la classe
 
Le compilateur me met le message suivant:
 
 
cannot convert 'this' pointer from 'const class CClipScanPilote' to 'class CClipScanPilote &'
 
qqn aurait un idée de la source du pb !?? Je galère un peu là, ça serai bien sympa ! :sarcastic:

Reply

Marsh Posté le 04-10-2001 à 15:20:36   

Reply

Marsh Posté le 04-10-2001 à 15:56:23    

Ce qui me choque c'est le  
int IsisScan(const CClipScanPilote& _piloteDlg = NULL);  
essaye deja en enlevant le "=NULL" qui ne doit pas etre compatible avec la classe CClipScanPilote :D
 
Ensuite donne le proto de la methode IncrCompteur, qui si la logique est respectee, doit incrementer un compteur (je suppose) et ne doit donc pas etre CClipScanPilote::IncrCompteur(void) const, et ne peut donc pas etre appele sur une const reference...
 
d'ou IsisScan a pour prototype
 
int IsisScan(CClipScanPilote& _piloteDlg );
 
Maintenant, comme IsisScan modifie la classe CClipScanPilote je preconise de passer un pointeur afin de mieux le montrer ce qui te permet alors de retrouver ton argument par default :
int IsisScan(CClipScanPilote* _piloteDlg = NULL);

 

[edtdd]--Message édité par BENB--[/edtdd]

Reply

Marsh Posté le 04-10-2001 à 16:03:35    

...tu connais pas le principe de la référence, non !?
le fait qu'il y ai un & juste avant le _pilotDlg, ça veux dire que je passe pas l'objet même, mais son adresse. Du coup, je dis que si on passe pas d'adresse, le paramètre comporte un adresse nulle. Après, je fais un test avant d'appliquer une méthode comme g mis dans l'exemple (merci d'ailleur, j'oubliais le test:D ), j'fais donc:
 
if ( &_pilotDlg != NULL)
   _pilotDlg.IncrCompteur();

Reply

Marsh Posté le 04-10-2001 à 16:14:48    

Ce qui est incroyable, c'est ta capacite a m'insulter quoi que je te reponde :D
 
non je n'ai jamais vue mettre une reference a NULL, on m'a toujours dit que c'etait impossible (j'en suis desolee) et je conseille d'essayer sans. Ceci dit je n'ai pas dit que c'etait ca
 
Le probleme viens plus probablement du const...

Reply

Marsh Posté le 04-10-2001 à 16:18:34    

y fallait pas vivre ça comme une agression, c'en était pas du tout une ! Et si tu l'as pris comme tel, j'en suis désolé :jap: (ça va, ça fait pas trop faux cul là ?:D )
 
Je te demandais si tu connaissais, t'aurais pu ne pas voir le "&" ...
 
Sinon, c clair que l'erreur est liée au const, mais si je le met pas, y me fait un message d'erreur aussi !
...jammais content ce compilo ! :gun:

 

[edtdd]--Message édité par El_Gringo--[/edtdd]

Reply

Marsh Posté le 04-10-2001 à 16:22:20    

Il te met quoi comme message ss le const???
 
Sinon fait tt simplement le passage par adresse!! Une référence c exactement la même chose sauf que c plus dangeureux car on oublie facilement que c une adresse!! ;)


---------------
Athlon64 s754 10*200MHz - R9800Pro - 512MB DDR200MHz - ZX6RR - Q2[SupOp] - Tutorial Video: multilangues, multisstitres
Reply

Marsh Posté le 04-10-2001 à 16:24:43    

c ce que g fini par faire : passage par adresse. Mais je suis qd même curieux !
 et puis, c peut être plus dangereux, mais c plus joli une référence !:D

Reply

Marsh Posté le 04-10-2001 à 16:26:24    

Quelle erreur as-tu lorsque tu enleve le const ?
c'est a l'appel de IsisScan ?
il est possible que a l'appel de IsisScan tu ais un const deja...
 
Solution 1 Propre -> se debrouiller pour ne plus avoir de const a l'appel de IsisScan (facile a dire... a faire ??? je ne connais pas ton code)
 
Solution 2 Plutot Crade -> Il y a une option mobile ou moveable je crois a mettre devant les elements que tu modifies dans ta classe, cet option permet de modifier cet element dans une classe const (je m'en sert pour mes Mutex de classes par exemple)
 
Solution 3 Franchement crade -> un cast pour faire sauter le const (Attention danger)
a - const_cast<CClipScanPilote&>(_piloteDlg )....
b - (CClipScanPilote&)(_piloteDlg)....

Reply

Marsh Posté le 04-10-2001 à 17:03:40    

une référence n'est jamais nulle, c'est un avantage sur un pointeur : on est sûr d'avoir un objet (plus de if (!param) return ...)
 
pour le 'mobile' ou 'moveable' dont parle benb, son petit nom est 'mutable'.

Reply

Marsh Posté le 04-10-2001 à 17:22:28    

youdontcare faux!! Une référence peut être nulle:
 
L´utilisateur a l´adresse d´un int (obtenue d´un tiers donc il l´a pas initialisée, peut être nulle ou non nulle)..
 
int* _i_Value;
 
void toto(int& i)
{
i++;
};
 
L´utilisateur arrive avec ses gros sabots:
 
toto(*_i_Value);
 
Et hop access violation si _i_Value était nul..
Résultat c encore pire car ds ta fonction tu peux pas détecter une erreur de l´utilisateur, tu te contentes de planter..  :D

Reply

Marsh Posté le 04-10-2001 à 17:22:28   

Reply

Marsh Posté le 04-10-2001 à 17:28:57    

:jap:
 
(petit pinailleur va :D)

Reply

Marsh Posté le 04-10-2001 à 17:31:08    

H4dd3R a écrit a écrit :

youdontcare faux!! Une référence peut être nulle:
 
L´utilisateur a l´adresse d´un int (obtenue d´un tiers donc il l´a pas initialisée, peut être nulle ou non nulle)..
 
int* _i_Value;
 
void toto(int& i)
{
i++;
};
 
L´utilisateur arrive avec ses gros sabots:
 
toto(*_i_Value);
 
Et hop access violation si _i_Value était nul..
Résultat c encore pire car ds ta fonction tu peux pas détecter une erreur de l´utilisateur, tu te contentes de planter..  :D  




Bien sur si tu mélange les pointeurs et le références ça va merder. Mais c'est pas le but.
De tout façon des que tu utilises les pointeurs tu peux faire n'importe quoi, même écrire dans le bios, alors....

Reply

Marsh Posté le 04-10-2001 à 17:38:55    

seblamb youdontcare disait qu´une référence permettait de se protéger plus de l´utilisateur..
 
J´ai juste montré que non ça protégait pas plus (car si l´utilisateur a instancié lui même sa variable ça plantera jamais même par passage d´adresse)..
 
Et sinon je suis d´accord avec les pointeurs on peut tt faire, avec les références aussi (vu que c la même chose)..
 
Je veux juste dire n´utilisez pas les ref ça sert à rien (ou alors passez au java où le mot référence mérite son nom)..  :D

 

[edtdd]--Message édité par H4dd3R--[/edtdd]

Reply

Marsh Posté le 04-10-2001 à 19:39:43    

bof, dire que l'on doit pas utiliser de ref c'est un peu osé
tu fais comment pour redefinir l'operateur = (et les autres operateurs), le constructeur de recopie etc, etc. C'est un element incompressible du langage.
 
De plus, le code suivant, tu le coderais comment sans reference:
 
void toto(const string &titi)
{
  string tata= titi;
}
 
surment pas avec des pointeurs et avec un objet c'est lourdingue => ref. Faut juste savoir ce que l'on fait...

Reply

Marsh Posté le 05-10-2001 à 10:09:51    

Merci Youdontcare, impossible de retrouver ce mot-cle...
 
H4dd3R > tu as raison on peut faire du C++  sans utiliser de references, sans utiliser d'objets, sans utiliser de structures...
mais bon dans ce cas la on fait du FORTRAN en C pas du C++ :D
 
Les references sont utiles, en particulier pour des retours de fonctions ou elle permettent une plus grande velocite en etant plus faciles que des pointeurs (surcharges des operateurs [] par ex).
 
Par contre il est impossible d'affecter NULL a une reference, (j'ai verifie) ce qui me parait plutot rassurant.
 
Je ne considere pas le cas de H4dd3R, car ce n'est pas la reference que l'on affecte a NULL, l'erreur est ailleurs (il est stupide d'ecrire *ptr, si ptr pointe n'importe ou, premiere lecon sur les pointeurs) car quelque soit la fonction qui est derriere la fonction plante (que l'on passe un pointeur, une reference ou une valeur...)

Reply

Marsh Posté le 05-10-2001 à 10:31:39    

Des petits commentaires:
 
wpk
tu fais comment pour redefinir l'operateur = (et les autres operateurs), le constructeur de recopie etc, etc.
Je redéfinis ces opérateurs ds mes propres classes, car ces opérateurs sont foireux, dans ton exemple:
void toto(const string &titi)  
{  
 string tata= titi;  
}

l´opérateur = ne rend pas d´erreur si la copie n´a pas pu être effectuée.. (comme bcp de classe de microschrott celle ci mauque cruellement de gestion d´erreurs -ya même pas d´exceptions-)
surment pas avec des pointeurs et avec un objet c'est lourdingue
Perso si dans ton cas j´ai un objet string qui dispose d´une fonction copyto() (qui elle rend un beau message d´erreur au cas où).
BENB:
tu as raison on peut faire du C++  sans utiliser de references, sans utiliser d'objets, sans utiliser de structures...
Je t´arrête à "sans utiliser d'objets".. Je refais tt en objets, et en objets un peu mieux que ceux de win (heureusement)..
Je ne considere pas le cas de H4dd3R, car ce n'est pas la reference que l'on affecte a NULL, l'erreur est ailleurs (il est stupide d'ecrire *ptr, si ptr pointe n'importe ou, premiere lecon sur les pointeurs) car quelque soit la fonction qui est derriere la fonction plante (que l'on passe un pointeur, une reference ou une valeur...)
Ben justement on est d´accord: de tte façon, si ptr pointe n'importe ou, ça plante, si ptr est ok, c bon, et ceci aussi bien avec des refs qu´avec des adresses.. Donc aucun avantage aux refs.. (je vois tjrs que des désavantages pour l´instant!! :) )

Reply

Marsh Posté le 05-10-2001 à 11:42:17    

H4dd3R a écrit a écrit :

Ben justement on est d´accord: de tte façon, si ptr pointe n'importe ou, ça plante, si ptr est ok, c bon, et ceci aussi bien avec des refs qu´avec des adresses.. Donc aucun avantage aux refs.. (je vois tjrs que des désavantages pour l´instant!! :) )  




Le but c'est de ne pas avoir de pointeur, donc évidemment si tu met de pointeurs au millieu, ce n'est plus cohérent.
Imaginont l'appli parfaite sans pointeur, si tu n'utilises que des objet et des référence tu n'auras jamais de pointeur null.
 
Maintenant la réalité, à cause de l'existant, il faut des fois utiliser les pointeurs, c'est au moment du passage du pointeur aux reférences qu'il faut faire attention ( tests ...)

Reply

Marsh Posté le 05-10-2001 à 11:44:34    

H4dd3R > tu ajoute un pointeur avec le quel tu fais une connerie, et tu dis que c'est de la faute de la reference... :lol:
 
la reference est bonne dans ton exemple, c'est le dereferencement du pointeur qui est mauvais, change le pointeur contre une reference et recommence, et tu verra, ca marchera...

Reply

Marsh Posté le 05-10-2001 à 12:29:20    

Je dois avoir du mal à m´exprimer..
 
[BENB]
tu ajoute un pointeur avec le quel tu fais une connerie, et tu dis que c'est de la faute de la reference...
Ben oui je dis par là que les références (en C) c pas terrible car pas sécurisé (la preuve on peut les faire pointer sur un objet inexistant)..
 
[seblamb]
Imaginont l'appli parfaite sans pointeur, si tu n'utilises que des objet et des référence tu n'auras jamais de pointeur null.
Je suis d´accord avec toi d´ailleurs ça s´appelle Java (par exemple)..
Ce que je veux dire c qu´en C à cause des pointeurs qui trainent il est pas possible de faire de la bonne programmation objet..
Dans le cas général tu fais pas tte ton app tt seul mais tu fais des modules que d´autres utiliseront. Et là l´app parfaite tu peux l´oublier car c pas avec de pauvres références que tu te protégeras de l´utilisateur de ton module.. ;)
 
Et dans le cas d´une app "tt tt seul" ben ton app parfaite tu peux la faire aussi bien avec des ponteurs..
En gros je vois des  :lol: (BENB ;) ), mais tjrs aucun argument valable pour les références..  :)

 

[edtdd]--Message édité par H4dd3R--[/edtdd]

Reply

Marsh Posté le 05-10-2001 à 12:39:42    

Avec JAVA c'est pareil, le références NULL sur un objet ça existe aussi ( "Null pointer exception" ). En Delphi aussi.  
 
Pour ce qui est de la protection, de toute façon le C++ n'est pas un forteresse et c'est pas le but. Ca permet juste de faire un control pour éviter les erreurs.  
C'est sur pour programmer en C++ il faut connaitre le C++ et pas seulement le C, ce qui est malheureusement pas souvant le cas.

Reply

Marsh Posté le 05-10-2001 à 13:26:29    

Mais que veux tu comme arguments...
la reference limites les risques d'erreurs et est plus faciles a utiliser... c'est tout.
Pour une fonction prendre un reference plutot qu'un pointeur c'est justement eviter le cas des pointeurs NULL, cela permet egalement de gagner en vitesse et passer des const toto& plutot que des toto... ainsi que la posibilite d'avoir des surchages de operator[] qui semblent retourner une valeur.
 
Oui c'est une forme plus facile et plus sure des pointeurs, maintenant je n'en suis pas fan
 
Je me permet de revenir sur l'exemple que tu donnes, c'est au niveau de ton pointeur que se trouve l'erreur et non au niveau de la reference, je ne vois absolument pas en quoi cet exemple discredite la reference, au contraire, il est impossible de faire cela avec une reference. Pour qu'une reference pointe n'importe ou il faut l'initialiser avec un pointeur ou l'utiliser en-dehors de son contexte.  
Comme cela a deja ete dit, pour faire du C++ il faut connaitre le langage.  
Pour une methode il existe des pre-conditions....
forcement si tu ne les respectes pas...

 

[edtdd]--Message édité par BENB--[/edtdd]

Reply

Marsh Posté le 05-10-2001 à 14:10:44    

BENB
Pour une fonction prendre un reference plutot qu'un pointeur c'est justement eviter le cas des pointeurs NULL
Ben justement non cf mon exemple!!
C vonlontaire que je fasse n´importe quoi et c bien le but!!
Si tu appelles toi même ta fct tu vas pas faire d´erreur en passant la référence.. Tt comme en passant un pointeur..
Par contre si qqun d´autre appelle ta fct il peut aussi bien la faire planter avec une référence qu´avec un pointeur..
UNE REFERENCE C UN POINTEUR EN C!! En java ya le garbage collector qui apporte qd même un degré de sécurité en plus (pour l´exception seblamb je savais pas et j´avoue que je suis déçu)..
cela permet egalement de gagner en vitesse et passer des const toto& plutot que des toto
Oui ben forcément on n´a pas les mêmes buts, moi je recherche la sécurité pas la vitesse.. Si une fct prend un pointeur/ref chez moi, c qu´elle va modifier toto. Sinon elle se prend un copy constructor!!
Pour une methode il existe des pre-conditions....  
forcement si tu ne les respectes pas...

Tu les respectes pas moins en passant une ref nulle qu´un pointeur nul!! ;)
 
bon voila.. Et puis j´ai l´impression que on tourne un peu en rond là.. Tant pis..  :(

 

[edtdd]--Message édité par H4dd3R--[/edtdd]

Reply

Marsh Posté le 05-10-2001 à 14:27:47    

Hé bah, vous vous êtes enflammés sur mon topic ! :hot:  
G fini par laisser tomber les références, j'utilise un pointeur, tout vas très bien, et c tant mieux. Par contre, je garde vos commentaires à tous bien au chaud sur mon dur... si g à nouveau des envies de références !:D
 
Merci à tous... :hello:

Reply

Marsh Posté le 05-10-2001 à 14:55:15    

H4dd3R > ton exemple est mauvais, puisque l'erreur c'est d'ecrire *ptr alors que ptr pointe n'importe ou, et la reference n'a rien a voir.
si tu fais
vois toto(int toto)
 
int *ptr
toto(*ptr); ca plantera au moment l'appel...
la reference n'est donc pas en cause puisque meme en la retirant ca ne marche toujours pas...
 
En fait voici un bon exemple du danger des references...
int& toto(void)
{
   int result;
   ...
   return result;
}
La reelement il y a danger a cause de la reference. Pas dans ton exemple...

 

[edtdd]--Message édité par BENB--[/edtdd]

Reply

Marsh Posté le 05-10-2001 à 15:07:05    

c'est pas trop grave VC++6 retourne dans ce cas :
 
warning C4172: returning address of local variable or temporary

Reply

Marsh Posté le 05-10-2001 à 15:18:09    

seblamb a écrit a écrit :

c'est pas trop grave VC++6 retourne dans ce cas :
 
warning C4172: returning address of local variable or temporary  




Je trouve que un warning c'est un leger pour le coup...
 
Mais c'est la seule utilisation dangereuse des references a mon humble avis...
 
l'exemple donne par H4dd3R concernant les pointeurs... et non les references...
 
A propos H4ddr3R si tu utilises des passges par valeurs chaque fois que tu n'as pas besoin de modifier un objet tu n'as pas de Pb de polymorphisme ?

Reply

Marsh Posté le 05-10-2001 à 16:21:30    

[grande geule on]

  • La vérification de type de C++ protège des erreurs de conception, pas d'utilisation.
  • Que l'on recoive un pointeur ou une référence (qui est un pointeur déguisé), on peut vouloir vérifier sa validité ou pas.


  • En C++ les références sont considérée désignant toujours un objet (donc &réf==NULL est incorrect).
  • En Java les références nulles sont normales.
  • Maintenant, si quelq'un fait *NULL ou NULL->Machin, il aura forçémment des problèmes, que se soit par pointeur ou en passant par une référence.
wpk a écrit a écrit :

le code suivant, tu le coderais comment sans reference:
 
void toto(const string &titi)
{
  string tata= titi;
}



void toto(const string *titi)
{
  string tata= *titi;
}
Ça revient strictementement au même, ou alors j'ai rien compris !
 
El_Gringo->
Je crois que ta fonction (qui est de toutes façon incorrecte donc), aurait du être déclarée comme ça:
    int IsisScan(const CClipScanPilote& _piloteDlg = *NULL);
au lieu de:
    int IsisScan(const CClipScanPilote& _piloteDlg = NULL);
 
[grande geule toujours on]

 

[edtdd]--Message édité par brunomailly--[/edtdd]


---------------
Pourquoi les cartes mères ont-elles des noms à coucher dehors ?
Reply

Marsh Posté le 08-10-2001 à 14:05:18    

Ahh il ma manquait un petit brunomailly pour confirmer qu´un pointeur et une ref c du kif!! :)
 
BENB
A propos H4ddr3R si tu utilises des passges par valeurs chaque fois que tu n'as pas besoin de modifier un objet tu n'as pas de Pb de polymorphisme ?
Ben non je vois pas.. Donne moi un exemple???  :)

Reply

Marsh Posté le 09-10-2001 à 10:11:02    

Attention ! J'ai pas dis que c'était pareil !
 
Il y a certes des similitudes entre pointeur et référence :
-Pas indispensable de connaître la définition de la classe cible.
-Mêmes règles de conversion implicite "est un".
-Le référence est sûrement implémentée sous la forme d'un pointeur caché.
 
Mais il y a des différences :
-Pas de référence NULL.
-Pas de référence void.
-Quand on utilise une référence, on n'a à priori pas besoin de savoir que c'est une référence.
 
Les deux ne sont donc pas librement interchangeables.
 
A noter que ceci s'applique au C++.
La référence JAVA équivaut à un pointeur C avec une syntaxe de référence C++, sans la notion de type void. D'où une utilisation différente.


---------------
Pourquoi les cartes mères ont-elles des noms à coucher dehors ?
Reply

Marsh Posté le 09-10-2001 à 11:58:13    

Bonjour, voila, je reviens parce que, bien que g résolu mon pb avec des pointeurs. ça m'travailleis cette histoire, d'autant plus, je me doutais que c'était un problème tout con.¨Personne ne pouvais le résoudre puisque je n'vous avais pas donné le bout de code nécessaire. En fait, je savais pas vraiement utiliser le références. à l'appel de la fonction IsisScan, je passais comme paramètre l'adresse de pilotDlg (soit: &pilotDlg), ce qui me paraissait logique. Alors qu'apparement, il faut passer directement l'instance pilotDlg.  
En fait, a part lors de la decription des paramètres de la fonction (IsisScan ici), l'utilisation de références est complètement transparente. tout se passe de la même façon que si on passait l'objet pilotDlg en argument (en apparence seulement, je sais !)
 
Merci tout l'monde, encore un fois...
C beau qd même cette solidarité... ça m'emeut tient :sweat:

Reply

Marsh Posté le 09-10-2001 à 17:17:34    

Bien dit http://forum.hardware.fr/icones/icon14.gif


---------------
Pourquoi les cartes mères ont-elles des noms à coucher dehors ?
Reply

Marsh Posté le 09-10-2001 à 17:20:56    

brunomailly a écrit a écrit :

Bien dit http://forum.hardware.fr/icones/icon14.gif  




 
à propos de quoi !? ...des références ou de la beauté de cette solidarité ?

Reply

Marsh Posté le 11-10-2001 à 15:32:41    

Parceque tu reconnais tes erreurs.
Parceque tu as trouvé la solution à ton problème.
Parceque tu laisse pas tomber le topic, tu viens conclure l'histoire.
Parceque tu nous remercie.
 
Tout ça, quoi !


---------------
Pourquoi les cartes mères ont-elles des noms à coucher dehors ?
Reply

Marsh Posté le 11-10-2001 à 17:06:20    

C'est vrai que c'est bien de finir un topic quand on trouve la (une ?) solution...
 
Et surtout quand il s'agit de de dire... que c'etait pas dans le code soumis au debut du topic... :D
 
Donc, surtout parce que je n'hesite pas a te fustiger au besoin,
BRAVO !

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed