je suis en train de me familiariser avec le c++
J'ai donc 2 questions :
- Pouvez vous me dire pourquoi mon code ci-dessous ne compile pas.
Je peux le faire compiler en déclarant foo comme étant une fonction
acceptant un objet de type const.
Mais je comprend pas ce que ca fait exactement.
De ce que j'en ai lu, c'est que quand on met const, cela permet
d'empecher la modification d'une variable, mais la je ne comprend pas
trop.
#include <iostream>
class A
{
};
class B: public A
{
};
void foo (A &arg)
{
}
int main (int argc, const char * argv[])
{
B myObjectB;
foo((A)myObjectB);
return 0;
}
- Quel est la différence entre passer un objet a une fonction en tant
que pointeur (*) et le passer en tant que référence (&). Dans les 2
cas, s'agit-il d'une adresse.
J'ai bien compris que cela nous permet de ne pas faire une recopie de
l'objet (passage par valeur), en passant une référence, mais ensuite
je ne connais pas la différence entre * et &.
Dans quel cas utiliser l'un ou l'autre.
De plus j'ai trouvé ce lien très intéressant sur const.
Mais je dois dire que je me comprend pas tout.
- L'auteur parle "d'object slicing" quand on passe un objet par
valeur.
Qu'est-ce que cela veut dire ?
int main (int argc, const char * argv[]) { B myObjectB; foo((A)myObjectB);
Pourquoi le cast ? foo() attend une référence à A, le cast devrait être (A&), mais ce n'est pas nécessaire ici puisqu'un B est aussi un A.
En fait en C++, tu ne devrais pas avoir à utiliser de cast en situation normale (contrairement à C où si l'on veut faire de l'OOP, c'est le castodrome).
return 0; }
- Quel est la différence entre passer un objet a une fonction en tant que pointeur (*) et le passer en tant que référence (&). Dans les 2 cas, s'agit-il d'une adresse.
Touché. En fait, techniquement c'est pareil.
J'ai bien compris que cela nous permet de ne pas faire une recopie de l'objet (passage par valeur), en passant une référence, mais ensuite je ne connais pas la différence entre * et &.
La différence est surtout sémantique... tu manipules une référence comme si c'était l'objet lui-même, mais le compilo se débrouille pour qu'en fait cela se passe à travers un pointeur. Ainsi tu utilises . plutôt que -> pour accéder aux membres.
Mais ça ne veut pas dire que les pointeurs sont devenus inutiles.
Dans quel cas utiliser l'un ou l'autre.
Dépend de la sémantique que tu veux utiliser dans le contexte (paramètres et retour de fonction). Là je laisse la parole aux autres, car j'ai dans l'idée que les règles sont légèrement différentes et je ne veux pas dire de conneries. Personnellement, j'utilise les références surtout pour les operateurs, pour le reste c'est au feeling et à l'usage.
De plus j'ai trouvé ce lien très intéressant sur const.
Quel lien ?!
Mais je dois dire que je me comprend pas tout.
- L'auteur parle "d'object slicing" quand on passe un objet par valeur. Qu'est-ce que cela veut dire ?
Aucune idée (surtout sans le lien).
Merci pour vos réponses éclairées...
On fait ce qu'on peut :)
-- Tek
thitou wrote:
#include <iostream>
class A
{
};
class B: public A
{
};
void foo (A &arg)
{
}
int main (int argc, const char * argv[])
{
B myObjectB;
foo((A)myObjectB);
Pourquoi le cast ? foo() attend une référence à A, le cast devrait être
(A&), mais ce n'est pas nécessaire ici puisqu'un B est aussi un A.
En fait en C++, tu ne devrais pas avoir à utiliser de cast en situation
normale (contrairement à C où si l'on veut faire de l'OOP, c'est le
castodrome).
return 0;
}
- Quel est la différence entre passer un objet a une fonction en tant
que pointeur (*) et le passer en tant que référence (&). Dans les 2
cas, s'agit-il d'une adresse.
Touché. En fait, techniquement c'est pareil.
J'ai bien compris que cela nous permet de ne pas faire une recopie de
l'objet (passage par valeur), en passant une référence, mais ensuite
je ne connais pas la différence entre * et &.
La différence est surtout sémantique... tu manipules une référence comme
si c'était l'objet lui-même, mais le compilo se débrouille pour qu'en
fait cela se passe à travers un pointeur. Ainsi tu utilises . plutôt que
-> pour accéder aux membres.
Mais ça ne veut pas dire que les pointeurs sont devenus inutiles.
Dans quel cas utiliser l'un ou l'autre.
Dépend de la sémantique que tu veux utiliser dans le contexte
(paramètres et retour de fonction). Là je laisse la parole aux autres,
car j'ai dans l'idée que les règles sont légèrement différentes et je ne
veux pas dire de conneries. Personnellement, j'utilise les références
surtout pour les operateurs, pour le reste c'est au feeling et à l'usage.
De plus j'ai trouvé ce lien très intéressant sur const.
Quel lien ?!
Mais je dois dire que je me comprend pas tout.
- L'auteur parle "d'object slicing" quand on passe un objet par
valeur.
Qu'est-ce que cela veut dire ?
int main (int argc, const char * argv[]) { B myObjectB; foo((A)myObjectB);
Pourquoi le cast ? foo() attend une référence à A, le cast devrait être (A&), mais ce n'est pas nécessaire ici puisqu'un B est aussi un A.
En fait en C++, tu ne devrais pas avoir à utiliser de cast en situation normale (contrairement à C où si l'on veut faire de l'OOP, c'est le castodrome).
return 0; }
- Quel est la différence entre passer un objet a une fonction en tant que pointeur (*) et le passer en tant que référence (&). Dans les 2 cas, s'agit-il d'une adresse.
Touché. En fait, techniquement c'est pareil.
J'ai bien compris que cela nous permet de ne pas faire une recopie de l'objet (passage par valeur), en passant une référence, mais ensuite je ne connais pas la différence entre * et &.
La différence est surtout sémantique... tu manipules une référence comme si c'était l'objet lui-même, mais le compilo se débrouille pour qu'en fait cela se passe à travers un pointeur. Ainsi tu utilises . plutôt que -> pour accéder aux membres.
Mais ça ne veut pas dire que les pointeurs sont devenus inutiles.
Dans quel cas utiliser l'un ou l'autre.
Dépend de la sémantique que tu veux utiliser dans le contexte (paramètres et retour de fonction). Là je laisse la parole aux autres, car j'ai dans l'idée que les règles sont légèrement différentes et je ne veux pas dire de conneries. Personnellement, j'utilise les références surtout pour les operateurs, pour le reste c'est au feeling et à l'usage.
De plus j'ai trouvé ce lien très intéressant sur const.
Quel lien ?!
Mais je dois dire que je me comprend pas tout.
- L'auteur parle "d'object slicing" quand on passe un objet par valeur. Qu'est-ce que cela veut dire ?
Aucune idée (surtout sans le lien).
Merci pour vos réponses éclairées...
On fait ce qu'on peut :)
-- Tek
Fabien LE LEZ
On 4 Aug 2004 14:04:20 -0700, (thitou):
- Quel est la différence entre passer un objet a une fonction en tant que pointeur (*) et le passer en tant que référence (&). Dans les 2 cas, s'agit-il d'une adresse.
En pratique, c'est surtout une question d'écriture. Généralement, j'applique une règle simple : si je peux utiliser une référence, je le fais. Sinon, j'utilise un pointeur.
Un pointeur est un truc très concret : c'est à peu près une adresse mémoire. Il peut pointer vers NULL (0), valeur qui sert souvent pour indiquer qu'une action a échoué [malloc(), par exemple, et les anciennes versions de new]. Il peut pointer vers un objet, pas forcément tout le temps le même d'ailleurs. Exemple :
void f() { int *ptr= NULL;// Certains préfère "...= 0;" int i= 3, j= 4; ptr= &j; ptr= &i; }
Une référence est un concept plus abstrait, qui a un sens sémantique, mais pas de sens pour le processeur. Une référence sur un objet, c'est quasiment l'objet lui-même -- pendant toute sa vie, elle représentera le même objet.
Venons-en maintenant au passage de paramètres à une fonction. Le passage par référence constante (void f(int const&)), c'est quasiment la même chose que le passage par valeur, à ceci près qu'on économise une copie. Si le programme est bien fait, il ne devrait pas y avoir d'autres différences. Le passage par référence non-constante indique que la fonction modifie le paramètre. Ça permet à une fonction de retourner plus d'un objet. Exemple :
Le passage par pointeur a ceci d'intéressant qu'il est à la fois un passage par adresse (ce qui évite la copie, et permet à la fonction de modifier le paramètre s'il est non-const) et un passage par valeur d'un objet de type "pointeur". Perso, je l'utilise assez rarement, et quand je l'utilise, c'est souvent pour avoir la possibilité de passer NULL.
void f1() { cout << "Resultat de la lecture : " << LectureOK (NULL) << endl; }
void f2() { int entier_lu; cout << "Resultat de la lecture : " << LectureOK (&entier_lu) << endl; cout << "L'entier lu est " << entier_lu << endl; }
C'est pas super-propre, mais ça rend parfois des services ;-)
Dernier point : un pointeur, contrairement à une référence, est un objet à part entière, il peut donc être paramètre de template. Par exemple, on peut stocker des pointeurs dans un vector<>, pas des références.
-- ;-)
On 4 Aug 2004 14:04:20 -0700, thitou@bigfoot.com (thitou):
- Quel est la différence entre passer un objet a une fonction en tant
que pointeur (*) et le passer en tant que référence (&). Dans les 2
cas, s'agit-il d'une adresse.
En pratique, c'est surtout une question d'écriture.
Généralement, j'applique une règle simple : si je peux utiliser une
référence, je le fais. Sinon, j'utilise un pointeur.
Un pointeur est un truc très concret : c'est à peu près une adresse
mémoire. Il peut pointer vers NULL (0), valeur qui sert souvent pour
indiquer qu'une action a échoué [malloc(), par exemple, et les
anciennes versions de new]. Il peut pointer vers un objet, pas
forcément tout le temps le même d'ailleurs.
Exemple :
void f()
{
int *ptr= NULL;// Certains préfère "...= 0;"
int i= 3, j= 4;
ptr= &j;
ptr= &i;
}
Une référence est un concept plus abstrait, qui a un sens sémantique,
mais pas de sens pour le processeur. Une référence sur un objet, c'est
quasiment l'objet lui-même -- pendant toute sa vie, elle représentera
le même objet.
Venons-en maintenant au passage de paramètres à une fonction.
Le passage par référence constante (void f(int const&)), c'est
quasiment la même chose que le passage par valeur, à ceci près qu'on
économise une copie. Si le programme est bien fait, il ne devrait pas
y avoir d'autres différences.
Le passage par référence non-constante indique que la fonction modifie
le paramètre. Ça permet à une fonction de retourner plus d'un objet.
Exemple :
Le passage par pointeur a ceci d'intéressant qu'il est à la fois un
passage par adresse (ce qui évite la copie, et permet à la fonction de
modifier le paramètre s'il est non-const) et un passage par valeur
d'un objet de type "pointeur".
Perso, je l'utilise assez rarement, et quand je l'utilise, c'est
souvent pour avoir la possibilité de passer NULL.
void f1()
{
cout << "Resultat de la lecture : " << LectureOK (NULL) << endl;
}
void f2()
{
int entier_lu;
cout << "Resultat de la lecture : "
<< LectureOK (&entier_lu) << endl;
cout << "L'entier lu est " << entier_lu << endl;
}
C'est pas super-propre, mais ça rend parfois des services ;-)
Dernier point : un pointeur, contrairement à une référence, est un
objet à part entière, il peut donc être paramètre de template. Par
exemple, on peut stocker des pointeurs dans un vector<>, pas des
références.
- Quel est la différence entre passer un objet a une fonction en tant que pointeur (*) et le passer en tant que référence (&). Dans les 2 cas, s'agit-il d'une adresse.
En pratique, c'est surtout une question d'écriture. Généralement, j'applique une règle simple : si je peux utiliser une référence, je le fais. Sinon, j'utilise un pointeur.
Un pointeur est un truc très concret : c'est à peu près une adresse mémoire. Il peut pointer vers NULL (0), valeur qui sert souvent pour indiquer qu'une action a échoué [malloc(), par exemple, et les anciennes versions de new]. Il peut pointer vers un objet, pas forcément tout le temps le même d'ailleurs. Exemple :
void f() { int *ptr= NULL;// Certains préfère "...= 0;" int i= 3, j= 4; ptr= &j; ptr= &i; }
Une référence est un concept plus abstrait, qui a un sens sémantique, mais pas de sens pour le processeur. Une référence sur un objet, c'est quasiment l'objet lui-même -- pendant toute sa vie, elle représentera le même objet.
Venons-en maintenant au passage de paramètres à une fonction. Le passage par référence constante (void f(int const&)), c'est quasiment la même chose que le passage par valeur, à ceci près qu'on économise une copie. Si le programme est bien fait, il ne devrait pas y avoir d'autres différences. Le passage par référence non-constante indique que la fonction modifie le paramètre. Ça permet à une fonction de retourner plus d'un objet. Exemple :
Le passage par pointeur a ceci d'intéressant qu'il est à la fois un passage par adresse (ce qui évite la copie, et permet à la fonction de modifier le paramètre s'il est non-const) et un passage par valeur d'un objet de type "pointeur". Perso, je l'utilise assez rarement, et quand je l'utilise, c'est souvent pour avoir la possibilité de passer NULL.
void f1() { cout << "Resultat de la lecture : " << LectureOK (NULL) << endl; }
void f2() { int entier_lu; cout << "Resultat de la lecture : " << LectureOK (&entier_lu) << endl; cout << "L'entier lu est " << entier_lu << endl; }
C'est pas super-propre, mais ça rend parfois des services ;-)
Dernier point : un pointeur, contrairement à une référence, est un objet à part entière, il peut donc être paramètre de template. Par exemple, on peut stocker des pointeurs dans un vector<>, pas des références.
-- ;-)
Fabien LE LEZ
On 4 Aug 2004 14:04:20 -0700, (thitou):
- L'auteur parle "d'object slicing" quand on passe un objet par valeur.
struct A { int a; };
struct B: A { int b; };
void f (A objet);
int main() { B objet; // Cet objet contient deux entiers, a et b. f (objet); /* Ici, tu passes un objet de classe A, copié à partir de "objet". Comme c'est un A, seul "a" a été copié, pas "b". Ainsi, on n'a copié qu'une partie de l'objet ; l'objet a en quelque sorte été "coupé" ("sliced", en anglais -- d'où le nom) */ }
Essaie le programme suivant :
struct A { virtual char const* f() const { return "Ceci est un A"; } };
struct B: A { virtual char const* f() const { return "Ceci est un B"; } };
void ParValeur (A a) { cout << a.f() << endl; }
void ParReference (A const& a) { cout << a.f() << endl; }
int main() { B b; ParValeur (b); ParReference (b); }
Je ne pense pas qu'il y ait une réelle différence (en-dehors de la copie) entre les deux versions si A n'a pas de fonctions virtuelles, mais je peux me tromper.
-- ;-)
On 4 Aug 2004 14:04:20 -0700, thitou@bigfoot.com (thitou):
- L'auteur parle "d'object slicing" quand on passe un objet par
valeur.
struct A
{
int a;
};
struct B: A
{
int b;
};
void f (A objet);
int main()
{
B objet; // Cet objet contient deux entiers, a et b.
f (objet); /* Ici, tu passes un objet de classe A, copié à partir
de "objet". Comme c'est un A, seul "a" a été copié, pas "b". Ainsi, on
n'a copié qu'une partie de l'objet ; l'objet a en quelque sorte été
"coupé" ("sliced", en anglais -- d'où le nom)
*/
}
Essaie le programme suivant :
struct A
{
virtual char const* f() const { return "Ceci est un A"; }
};
struct B: A
{
virtual char const* f() const { return "Ceci est un B"; }
};
void ParValeur (A a)
{
cout << a.f() << endl;
}
void ParReference (A const& a)
{
cout << a.f() << endl;
}
int main()
{
B b;
ParValeur (b);
ParReference (b);
}
Je ne pense pas qu'il y ait une réelle différence (en-dehors de la
copie) entre les deux versions si A n'a pas de fonctions virtuelles,
mais je peux me tromper.
- L'auteur parle "d'object slicing" quand on passe un objet par valeur.
struct A { int a; };
struct B: A { int b; };
void f (A objet);
int main() { B objet; // Cet objet contient deux entiers, a et b. f (objet); /* Ici, tu passes un objet de classe A, copié à partir de "objet". Comme c'est un A, seul "a" a été copié, pas "b". Ainsi, on n'a copié qu'une partie de l'objet ; l'objet a en quelque sorte été "coupé" ("sliced", en anglais -- d'où le nom) */ }
Essaie le programme suivant :
struct A { virtual char const* f() const { return "Ceci est un A"; } };
struct B: A { virtual char const* f() const { return "Ceci est un B"; } };
void ParValeur (A a) { cout << a.f() << endl; }
void ParReference (A const& a) { cout << a.f() << endl; }
int main() { B b; ParValeur (b); ParReference (b); }
Je ne pense pas qu'il y ait une réelle différence (en-dehors de la copie) entre les deux versions si A n'a pas de fonctions virtuelles, mais je peux me tromper.
-- ;-)
Cyrille Karmann
Alexandre Bacquart disait:
thitou wrote:
- Quel est la différence entre passer un objet a une fonction en tant que pointeur (*) et le passer en tant que référence (&). Dans les 2 cas, s'agit-il d'une adresse.
Touché. En fait, techniquement c'est pareil.
A un détail près, je crois. Une référence se réfère toujours vers le même objet alors qu'un pointeur peut être modifié pour pointer à un autre endroit de la mémoire.
-- Cyrille
Alexandre Bacquart <tek512@hotmail.com> disait:
thitou wrote:
- Quel est la différence entre passer un objet a une fonction en tant
que pointeur (*) et le passer en tant que référence (&). Dans les 2
cas, s'agit-il d'une adresse.
Touché. En fait, techniquement c'est pareil.
A un détail près, je crois. Une référence se réfère toujours vers le
même objet alors qu'un pointeur peut être modifié pour pointer à un
autre endroit de la mémoire.
- Quel est la différence entre passer un objet a une fonction en tant que pointeur (*) et le passer en tant que référence (&). Dans les 2 cas, s'agit-il d'une adresse.
Touché. En fait, techniquement c'est pareil.
A un détail près, je crois. Une référence se réfère toujours vers le même objet alors qu'un pointeur peut être modifié pour pointer à un autre endroit de la mémoire.
-- Cyrille
Loïc Joly
thitou wrote:
Bonjour a tous,
je suis en train de me familiariser avec le c++ J'ai donc 2 questions :
- Pouvez vous me dire pourquoi mon code ci-dessous ne compile pas. Je peux le faire compiler en déclarant foo comme étant une fonction acceptant un objet de type const. Mais je comprend pas ce que ca fait exactement.
De ce que j'en ai lu, c'est que quand on met const, cela permet d'empecher la modification d'une variable, mais la je ne comprend pas trop.
#include <iostream>
class A {
};
class B: public A {
};
void foo (A &arg) {
}
int main (int argc, const char * argv[]) { B myObjectB; foo((A)myObjectB);
return 0; }
En plus des autres réponses, voilà ce qui se passe dans ton cas :
Tu convertis explicitement myObjectB en un objet de type A. Ce qui n'a rien à voir avec la conversion d'un B& vers un A&, ou d'un B* vers un A*. Dans les deux derniers cas, l'objet pointé ou référencé reste le même, mais on en a une vue restreinte à sa partie A.
Dans le cas en question, un nouvel objet est crée qui correspond à la partie A de myObjectB. Dit autrement, le cast fait apparaître un objet temporaire. C'est ce qu'on appèle du slicing.
Or, on ne peut pas passer un objet temporaire en tant que référence non constante, puisque passer un objet par référence indique qu'on va le modifier, mais comme il s'agit d'un temporaire, l'objet sera détruit et les modifications perdues.
int f(int &i) {i++;}
int g() { int a = 0; double b = 0; f(a); // Ok, maintenant, a vaut 1 f(a+1); // Pas ok, a+1 est un temporaire f(b); // Pas ok, la conversion de double en int crée un temporaire }
Par contre, s'il s'agit d'un passage par référence constante, comme on ne modifie pas l'objet passé, mais qu'on fait juste un passage qui ne demande pas de copier l'objet passé (qu'il soit temporaire ou non), on peut utiliser un objet temporaire.
int f(int const &i) { static int tot = 0; tot += i; // remarque : On ne peut pas écrire i++ ici }
int g() { int a = 1; double b = 39; f(a); // Ok, maintenant, tot vaut 1 f(a+1); // Ok, maintenant, tot vaut 3 f(b); // Ok, maintenant, tot vaut 42 }
-- Loïc
thitou wrote:
Bonjour a tous,
je suis en train de me familiariser avec le c++
J'ai donc 2 questions :
- Pouvez vous me dire pourquoi mon code ci-dessous ne compile pas.
Je peux le faire compiler en déclarant foo comme étant une fonction
acceptant un objet de type const.
Mais je comprend pas ce que ca fait exactement.
De ce que j'en ai lu, c'est que quand on met const, cela permet
d'empecher la modification d'une variable, mais la je ne comprend pas
trop.
#include <iostream>
class A
{
};
class B: public A
{
};
void foo (A &arg)
{
}
int main (int argc, const char * argv[])
{
B myObjectB;
foo((A)myObjectB);
return 0;
}
En plus des autres réponses, voilà ce qui se passe dans ton cas :
Tu convertis explicitement myObjectB en un objet de type A. Ce qui n'a
rien à voir avec la conversion d'un B& vers un A&, ou d'un B* vers un
A*. Dans les deux derniers cas, l'objet pointé ou référencé reste le
même, mais on en a une vue restreinte à sa partie A.
Dans le cas en question, un nouvel objet est crée qui correspond à la
partie A de myObjectB. Dit autrement, le cast fait apparaître un objet
temporaire. C'est ce qu'on appèle du slicing.
Or, on ne peut pas passer un objet temporaire en tant que référence non
constante, puisque passer un objet par référence indique qu'on va le
modifier, mais comme il s'agit d'un temporaire, l'objet sera détruit et
les modifications perdues.
int f(int &i) {i++;}
int g()
{
int a = 0;
double b = 0;
f(a); // Ok, maintenant, a vaut 1
f(a+1); // Pas ok, a+1 est un temporaire
f(b); // Pas ok, la conversion de double en int crée un temporaire
}
Par contre, s'il s'agit d'un passage par référence constante, comme on
ne modifie pas l'objet passé, mais qu'on fait juste un passage qui ne
demande pas de copier l'objet passé (qu'il soit temporaire ou non), on
peut utiliser un objet temporaire.
int f(int const &i)
{
static int tot = 0;
tot += i; // remarque : On ne peut pas écrire i++ ici
}
int g()
{
int a = 1;
double b = 39;
f(a); // Ok, maintenant, tot vaut 1
f(a+1); // Ok, maintenant, tot vaut 3
f(b); // Ok, maintenant, tot vaut 42
}
je suis en train de me familiariser avec le c++ J'ai donc 2 questions :
- Pouvez vous me dire pourquoi mon code ci-dessous ne compile pas. Je peux le faire compiler en déclarant foo comme étant une fonction acceptant un objet de type const. Mais je comprend pas ce que ca fait exactement.
De ce que j'en ai lu, c'est que quand on met const, cela permet d'empecher la modification d'une variable, mais la je ne comprend pas trop.
#include <iostream>
class A {
};
class B: public A {
};
void foo (A &arg) {
}
int main (int argc, const char * argv[]) { B myObjectB; foo((A)myObjectB);
return 0; }
En plus des autres réponses, voilà ce qui se passe dans ton cas :
Tu convertis explicitement myObjectB en un objet de type A. Ce qui n'a rien à voir avec la conversion d'un B& vers un A&, ou d'un B* vers un A*. Dans les deux derniers cas, l'objet pointé ou référencé reste le même, mais on en a une vue restreinte à sa partie A.
Dans le cas en question, un nouvel objet est crée qui correspond à la partie A de myObjectB. Dit autrement, le cast fait apparaître un objet temporaire. C'est ce qu'on appèle du slicing.
Or, on ne peut pas passer un objet temporaire en tant que référence non constante, puisque passer un objet par référence indique qu'on va le modifier, mais comme il s'agit d'un temporaire, l'objet sera détruit et les modifications perdues.
int f(int &i) {i++;}
int g() { int a = 0; double b = 0; f(a); // Ok, maintenant, a vaut 1 f(a+1); // Pas ok, a+1 est un temporaire f(b); // Pas ok, la conversion de double en int crée un temporaire }
Par contre, s'il s'agit d'un passage par référence constante, comme on ne modifie pas l'objet passé, mais qu'on fait juste un passage qui ne demande pas de copier l'objet passé (qu'il soit temporaire ou non), on peut utiliser un objet temporaire.
int f(int const &i) { static int tot = 0; tot += i; // remarque : On ne peut pas écrire i++ ici }
int g() { int a = 1; double b = 39; f(a); // Ok, maintenant, tot vaut 1 f(a+1); // Ok, maintenant, tot vaut 3 f(b); // Ok, maintenant, tot vaut 42 }
-- Loïc
Alexandre Bacquart
Cyrille Karmann wrote:
Alexandre Bacquart disait:
thitou wrote:
- Quel est la différence entre passer un objet a une fonction en tant que pointeur (*) et le passer en tant que référence (&). Dans les 2 cas, s'agit-il d'une adresse.
Touché. En fait, techniquement c'est pareil.
A un détail près, je crois. Une référence se réfère toujours vers le même objet alors qu'un pointeur peut être modifié pour pointer à un autre endroit de la mémoire.
Si j'ai dit que "techniquement" c'est pareil, c'est que techniquement c'est pareil :) Maintenant effectivement, les références se comportent un peu comme des pointeurs constants.
-- Tek
Cyrille Karmann wrote:
Alexandre Bacquart <tek512@hotmail.com> disait:
thitou wrote:
- Quel est la différence entre passer un objet a une fonction en tant
que pointeur (*) et le passer en tant que référence (&). Dans les 2
cas, s'agit-il d'une adresse.
Touché. En fait, techniquement c'est pareil.
A un détail près, je crois. Une référence se réfère toujours vers le
même objet alors qu'un pointeur peut être modifié pour pointer à un
autre endroit de la mémoire.
Si j'ai dit que "techniquement" c'est pareil, c'est que techniquement
c'est pareil :) Maintenant effectivement, les références se comportent
un peu comme des pointeurs constants.
- Quel est la différence entre passer un objet a une fonction en tant que pointeur (*) et le passer en tant que référence (&). Dans les 2 cas, s'agit-il d'une adresse.
Touché. En fait, techniquement c'est pareil.
A un détail près, je crois. Une référence se réfère toujours vers le même objet alors qu'un pointeur peut être modifié pour pointer à un autre endroit de la mémoire.
Si j'ai dit que "techniquement" c'est pareil, c'est que techniquement c'est pareil :) Maintenant effectivement, les références se comportent un peu comme des pointeurs constants.
-- Tek
Fabien LE LEZ
On Thu, 05 Aug 2004 00:24:41 +0200, Alexandre Bacquart :
(pointeurs/références)
techniquement c'est pareil.
Tu parles là de sémantique ou d'implémentation ?
-- ;-)
On Thu, 05 Aug 2004 00:24:41 +0200, Alexandre Bacquart
<tek512@hotmail.com>:
On Thu, 05 Aug 2004 00:24:41 +0200, Alexandre Bacquart :
(pointeurs/références)
techniquement c'est pareil.
Tu parles là de sémantique ou d'implémentation ?
-- ;-)
Horst Kraemer
(thitou) wrote:
Bonjour a tous,
je suis en train de me familiariser avec le c++ J'ai donc 2 questions :
- Pouvez vous me dire pourquoi mon code ci-dessous ne compile pas. Je peux le faire compiler en déclarant foo comme étant une fonction acceptant un objet de type const. Mais je comprend pas ce que ca fait exactement.
De ce que j'en ai lu, c'est que quand on met const, cela permet d'empecher la modification d'une variable, mais la je ne comprend pas trop.
#include <iostream>
class A {
};
class B: public A {
};
void foo (A &arg) {
}
int main (int argc, const char * argv[]) { B myObjectB; foo((A)myObjectB);
return 0; }
Il y a une grande différence entre
foo((A)myObjectB); // 1
et
foo((A&)myObjectB); // 2a
ou bien
foo(myObjectB); // 2b
ce qui est équivalent à la version précédente
et je crois que ton intention est plutot la version 2. La version 2 convertit l'objet myObjectB du type B en une référence sur A, Cela veut dire que la fonction foo manipule la "partie A" de myObjectB "en personne", c.a.d si tu changes un élément de arg dans foo ce changement se fait directement dans la partie A de myObjectB.
L'expression (A)myObjectB cependant convertit l'objet en un objet du type A par copie - c.a.d. elle extrait la partie A en coupant tout ce qui est extérieur à A (slicing) - et c'est la copie de la partie A de myObject B qui sera passée à la fonction foo. Bien entendu un changement d'un élément de arg n'a aucun effet sur l'objet myObjectB.
Le problème avec
foo((A)myObjectB)
est que (A)myObjectB n'est pas une "variable" mais seulement une copie temporaire d'une partie de myObjectB. Une règle du langage C++ dit qu'un objet temporaire du type A ne peut être accepté que par une référence sur const A et ne peut pas être passé à une référence sur A non constant.
-- Horst
-- Lâche pas la patate!
thitou@bigfoot.com (thitou) wrote:
Bonjour a tous,
je suis en train de me familiariser avec le c++
J'ai donc 2 questions :
- Pouvez vous me dire pourquoi mon code ci-dessous ne compile pas.
Je peux le faire compiler en déclarant foo comme étant une fonction
acceptant un objet de type const.
Mais je comprend pas ce que ca fait exactement.
De ce que j'en ai lu, c'est que quand on met const, cela permet
d'empecher la modification d'une variable, mais la je ne comprend pas
trop.
#include <iostream>
class A
{
};
class B: public A
{
};
void foo (A &arg)
{
}
int main (int argc, const char * argv[])
{
B myObjectB;
foo((A)myObjectB);
return 0;
}
Il y a une grande différence entre
foo((A)myObjectB); // 1
et
foo((A&)myObjectB); // 2a
ou bien
foo(myObjectB); // 2b
ce qui est équivalent à la version précédente
et je crois que ton intention est plutot la version 2. La version 2
convertit l'objet myObjectB du type B en une référence sur A, Cela
veut dire que la fonction foo manipule la "partie A" de myObjectB "en
personne", c.a.d si tu changes un élément de arg dans foo ce
changement se fait directement dans la partie A de myObjectB.
L'expression (A)myObjectB cependant convertit l'objet en un objet du
type A par copie - c.a.d. elle extrait la partie A en coupant tout ce
qui est extérieur à A (slicing) - et c'est la copie de la partie A de
myObject B qui sera passée à la fonction foo. Bien entendu un
changement d'un élément de arg n'a aucun effet sur l'objet myObjectB.
Le problème avec
foo((A)myObjectB)
est que (A)myObjectB n'est pas une "variable" mais seulement une copie
temporaire d'une partie de myObjectB. Une règle du langage C++ dit
qu'un objet temporaire du type A ne peut être accepté que par une
référence sur const A et ne peut pas être passé à une référence sur A
non constant.
je suis en train de me familiariser avec le c++ J'ai donc 2 questions :
- Pouvez vous me dire pourquoi mon code ci-dessous ne compile pas. Je peux le faire compiler en déclarant foo comme étant une fonction acceptant un objet de type const. Mais je comprend pas ce que ca fait exactement.
De ce que j'en ai lu, c'est que quand on met const, cela permet d'empecher la modification d'une variable, mais la je ne comprend pas trop.
#include <iostream>
class A {
};
class B: public A {
};
void foo (A &arg) {
}
int main (int argc, const char * argv[]) { B myObjectB; foo((A)myObjectB);
return 0; }
Il y a une grande différence entre
foo((A)myObjectB); // 1
et
foo((A&)myObjectB); // 2a
ou bien
foo(myObjectB); // 2b
ce qui est équivalent à la version précédente
et je crois que ton intention est plutot la version 2. La version 2 convertit l'objet myObjectB du type B en une référence sur A, Cela veut dire que la fonction foo manipule la "partie A" de myObjectB "en personne", c.a.d si tu changes un élément de arg dans foo ce changement se fait directement dans la partie A de myObjectB.
L'expression (A)myObjectB cependant convertit l'objet en un objet du type A par copie - c.a.d. elle extrait la partie A en coupant tout ce qui est extérieur à A (slicing) - et c'est la copie de la partie A de myObject B qui sera passée à la fonction foo. Bien entendu un changement d'un élément de arg n'a aucun effet sur l'objet myObjectB.
Le problème avec
foo((A)myObjectB)
est que (A)myObjectB n'est pas une "variable" mais seulement une copie temporaire d'une partie de myObjectB. Une règle du langage C++ dit qu'un objet temporaire du type A ne peut être accepté que par une référence sur const A et ne peut pas être passé à une référence sur A non constant.
-- Horst
-- Lâche pas la patate!
Fabien LE LEZ
On 4 Aug 2004 14:04:20 -0700, (thitou):
foo((A)myObjectB);
Ecris plutôt
foo (A (myObjectB));
D'une part, ça évitera un cast "à la C", avec le moment de doute qui va avec ; d'autre part, ça explicitera ce que fait ce code : il crée un objet A avec "myObjectB" comme paramètre du constructeur.
En fait, il tente d'appeler "A::A (B const&)", mais comme ce constructeur n'existe pas, il se rabat sur "A::A (A const&)".
-- ;-)
On 4 Aug 2004 14:04:20 -0700, thitou@bigfoot.com (thitou):
foo((A)myObjectB);
Ecris plutôt
foo (A (myObjectB));
D'une part, ça évitera un cast "à la C", avec le moment de doute qui
va avec ; d'autre part, ça explicitera ce que fait ce code : il crée
un objet A avec "myObjectB" comme paramètre du constructeur.
En fait, il tente d'appeler "A::A (B const&)", mais comme ce
constructeur n'existe pas, il se rabat sur "A::A (A const&)".
D'une part, ça évitera un cast "à la C", avec le moment de doute qui va avec ; d'autre part, ça explicitera ce que fait ce code : il crée un objet A avec "myObjectB" comme paramètre du constructeur.
En fait, il tente d'appeler "A::A (B const&)", mais comme ce constructeur n'existe pas, il se rabat sur "A::A (A const&)".
-- ;-)
Alexandre Bacquart
Fabien LE LEZ wrote:
On Thu, 05 Aug 2004 00:24:41 +0200, Alexandre Bacquart :
(pointeurs/références)
techniquement c'est pareil.
Tu parles là de sémantique ou d'implémentation ?
C'est bizarre mais je pensais que c'était clair. Surtout que je dis plus loin que la sémantique est différente, j'ai pas trop l'habitude de me contredire dans le même post.
-- Tek
Fabien LE LEZ wrote:
On Thu, 05 Aug 2004 00:24:41 +0200, Alexandre Bacquart
<tek512@hotmail.com>:
(pointeurs/références)
techniquement c'est pareil.
Tu parles là de sémantique ou d'implémentation ?
C'est bizarre mais je pensais que c'était clair. Surtout que je dis plus
loin que la sémantique est différente, j'ai pas trop l'habitude de me
contredire dans le même post.
On Thu, 05 Aug 2004 00:24:41 +0200, Alexandre Bacquart :
(pointeurs/références)
techniquement c'est pareil.
Tu parles là de sémantique ou d'implémentation ?
C'est bizarre mais je pensais que c'était clair. Surtout que je dis plus loin que la sémantique est différente, j'ai pas trop l'habitude de me contredire dans le même post.