visiblement, il faut mettre l'argument par défaut dans la définition du prototype, et non pas dans la déclaration de la fonction.
Il y a un mélange de terminologie, mais l'idée est là. L'argument par défaut n'a aucune utilité pour la fonction en elle-même, mais pour le code appelant.
void f (int n= 42);
int main() { f(); // Ici, le compilateur traduit ça par "f(42);" }
void f (int n) { /* f n'a aucun moyen de savoir quoi que ce soit à propos de l'argument par défaut -- elle reçoit un entier, point barre. */ ... }
On Sun, 06 Nov 2005 19:05:47 +0100, AG <ag@tb.fr>:
visiblement, il faut mettre l'argument par défaut dans la définition du
prototype, et non pas dans la déclaration de la fonction.
Il y a un mélange de terminologie, mais l'idée est là.
L'argument par défaut n'a aucune utilité pour la fonction en
elle-même, mais pour le code appelant.
void f (int n= 42);
int main()
{
f(); // Ici, le compilateur traduit ça par "f(42);"
}
void f (int n)
{ /* f n'a aucun moyen de savoir quoi que ce soit à propos de
l'argument par défaut -- elle reçoit un entier, point barre. */
...
}
visiblement, il faut mettre l'argument par défaut dans la définition du prototype, et non pas dans la déclaration de la fonction.
Il y a un mélange de terminologie, mais l'idée est là. L'argument par défaut n'a aucune utilité pour la fonction en elle-même, mais pour le code appelant.
void f (int n= 42);
int main() { f(); // Ici, le compilateur traduit ça par "f(42);" }
void f (int n) { /* f n'a aucun moyen de savoir quoi que ce soit à propos de l'argument par défaut -- elle reçoit un entier, point barre. */ ... }
AG
Fabien LE LEZ wrote:
On Sun, 06 Nov 2005 19:05:47 +0100, AG :
visiblement, il faut mettre l'argument par défaut dans la définition du prototype, et non pas dans la déclaration de la fonction.
Il y a un mélange de terminologie, mais l'idée est là. L'argument par défaut n'a aucune utilité pour la fonction en elle-même, mais pour le code appelant.
void f (int n= 42);
int main() { f(); // Ici, le compilateur traduit ça par "f(42);" }
void f (int n) { /* f n'a aucun moyen de savoir quoi que ce soit à propos de l'argument par défaut -- elle reçoit un entier, point barre. */ ... }
ok, Merci.
Fabien LE LEZ wrote:
On Sun, 06 Nov 2005 19:05:47 +0100, AG <ag@tb.fr>:
visiblement, il faut mettre l'argument par défaut dans la définition du
prototype, et non pas dans la déclaration de la fonction.
Il y a un mélange de terminologie, mais l'idée est là.
L'argument par défaut n'a aucune utilité pour la fonction en
elle-même, mais pour le code appelant.
void f (int n= 42);
int main()
{
f(); // Ici, le compilateur traduit ça par "f(42);"
}
void f (int n)
{ /* f n'a aucun moyen de savoir quoi que ce soit à propos de
l'argument par défaut -- elle reçoit un entier, point barre. */
...
}
visiblement, il faut mettre l'argument par défaut dans la définition du prototype, et non pas dans la déclaration de la fonction.
Il y a un mélange de terminologie, mais l'idée est là. L'argument par défaut n'a aucune utilité pour la fonction en elle-même, mais pour le code appelant.
void f (int n= 42);
int main() { f(); // Ici, le compilateur traduit ça par "f(42);" }
void f (int n) { /* f n'a aucun moyen de savoir quoi que ce soit à propos de l'argument par défaut -- elle reçoit un entier, point barre. */ ... }
ok, Merci.
kanze
AG wrote:
voilà ma question :
class A { int a; A(int m_a); };
A::A(int m_a=0) { a=m_a; }
class B : public A { int b; public: B(int m_b=0) {A(1);b=m_b;}; };
visiblement, il faut mettre l'argument par défaut dans la définition du prototype, et non pas dans la déclaration de la fonction. J'ai bon ?
Plus ou moins. On peut le mettre où on veut, mais il sert à l'appel. Si le compilateur le voit seulement.
Pourquoi ne peut-on pas le mettre dans les deux ?
Parce qu'ils pourrait se contredire. La norme permet une seule définition d'un paramètre par défaut parmi toutes les déclarations de la fonction visible. On *peut* faire des choses tordues :
extern void f( int = 1, int ) ; extern void f( int, int = 2 ) ;
mais je n'en vois pas l'intérêt (sauf peut-être l'obfuscation).
Note aussi que le paramètre par défaut ne fait nullement partie du type de la fonction, et qu'on peut écrire des choses comme :
extern void f( int = 1 ) ; void (*pf)( int = 2 ) = &f ;
Si on appelle f(), c'est l'équivalent de f(1), tandis que (*pf)() appelle f(2).
En somme, les paramètres par défaut sont associés au(x) declaration(s) qu'utilisent le compilateur lors de l'appel, et non à la fonction proprement dite.
-- James Kanze GABI Software Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
AG wrote:
voilà ma question :
class A
{
int a;
A(int m_a);
};
A::A(int m_a=0)
{
a=m_a;
}
class B : public A
{
int b;
public:
B(int m_b=0) {A(1);b=m_b;};
};
visiblement, il faut mettre l'argument par défaut dans la
définition du prototype, et non pas dans la déclaration de la
fonction. J'ai bon ?
Plus ou moins. On peut le mettre où on veut, mais il sert à
l'appel. Si le compilateur le voit seulement.
Pourquoi ne peut-on pas le mettre dans les deux ?
Parce qu'ils pourrait se contredire. La norme permet une seule
définition d'un paramètre par défaut parmi toutes les
déclarations de la fonction visible. On *peut* faire des choses
tordues :
extern void f( int = 1, int ) ;
extern void f( int, int = 2 ) ;
mais je n'en vois pas l'intérêt (sauf peut-être l'obfuscation).
Note aussi que le paramètre par défaut ne fait nullement partie
du type de la fonction, et qu'on peut écrire des choses comme :
extern void f( int = 1 ) ;
void (*pf)( int = 2 ) = &f ;
Si on appelle f(), c'est l'équivalent de f(1), tandis que
(*pf)() appelle f(2).
En somme, les paramètres par défaut sont associés au(x)
declaration(s) qu'utilisent le compilateur lors de l'appel, et
non à la fonction proprement dite.
--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
class B : public A { int b; public: B(int m_b=0) {A(1);b=m_b;}; };
visiblement, il faut mettre l'argument par défaut dans la définition du prototype, et non pas dans la déclaration de la fonction. J'ai bon ?
Plus ou moins. On peut le mettre où on veut, mais il sert à l'appel. Si le compilateur le voit seulement.
Pourquoi ne peut-on pas le mettre dans les deux ?
Parce qu'ils pourrait se contredire. La norme permet une seule définition d'un paramètre par défaut parmi toutes les déclarations de la fonction visible. On *peut* faire des choses tordues :
extern void f( int = 1, int ) ; extern void f( int, int = 2 ) ;
mais je n'en vois pas l'intérêt (sauf peut-être l'obfuscation).
Note aussi que le paramètre par défaut ne fait nullement partie du type de la fonction, et qu'on peut écrire des choses comme :
extern void f( int = 1 ) ; void (*pf)( int = 2 ) = &f ;
Si on appelle f(), c'est l'équivalent de f(1), tandis que (*pf)() appelle f(2).
En somme, les paramètres par défaut sont associés au(x) declaration(s) qu'utilisent le compilateur lors de l'appel, et non à la fonction proprement dite.
-- James Kanze GABI Software Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Fabien LE LEZ
On 7 Nov 2005 23:44:41 -0800, "kanze" :
extern void f( int = 1, int ) ;
extern void f( int, int = 2 ) ;
Ce n'est pas autorisé, ça, si ?
On 7 Nov 2005 23:44:41 -0800, "kanze" <kanze@gabi-soft.fr>:
class B : public A { int b; public: B(int m_b=0) {A(1);b=m_b;}; };
A noter que, sous réserve de déclarer le constructeur de A public, A::a vaut 0 après instanciation de B.
Cela vient du fait que dans
B(int m_b=0) {A(1);b=m_b;};
Le constructeur de A est appelé (avec sa valeur par défaut) avant même d'entrer dans les accolades. A(1) crée un objet A dans le vide. Ce que tu voulais faire est sûrement :
B(int m_b = 0) : A(1), b(m_b) {}
A::a vaut maintenant 1.
-- "Yo!" Martin Heidegger
Bonjour,
voilà ma question :
class A
{
int a;
A(int m_a);
};
A::A(int m_a=0)
{
a=m_a;
}
class B : public A
{
int b;
public:
B(int m_b=0) {A(1);b=m_b;};
};
A noter que, sous réserve de déclarer le constructeur de A public, A::a
vaut 0 après instanciation de B.
Cela vient du fait que dans
B(int m_b=0) {A(1);b=m_b;};
Le constructeur de A est appelé (avec sa valeur par défaut) avant même
d'entrer dans les accolades. A(1) crée un objet A dans le vide. Ce que
tu voulais faire est sûrement :
class B : public A { int b; public: B(int m_b=0) {A(1);b=m_b;}; };
A noter que, sous réserve de déclarer le constructeur de A public, A::a vaut 0 après instanciation de B.
Cela vient du fait que dans
B(int m_b=0) {A(1);b=m_b;};
Le constructeur de A est appelé (avec sa valeur par défaut) avant même d'entrer dans les accolades. A(1) crée un objet A dans le vide. Ce que tu voulais faire est sûrement :
B(int m_b = 0) : A(1), b(m_b) {}
A::a vaut maintenant 1.
-- "Yo!" Martin Heidegger
AG
Yoxoman wrote:
A noter que, sous réserve de déclarer le constructeur de A public, A::a vaut 0 après instanciation de B.
Cela vient du fait que dans
B(int m_b=0) {A(1);b=m_b;};
Le constructeur de A est appelé (avec sa valeur par défaut) avant même d'entrer dans les accolades. A(1) crée un objet A dans le vide. Ce que tu voulais faire est sûrement :
B(int m_b = 0) : A(1), b(m_b) {}
A::a vaut maintenant 1. Oui c'est ça que je voulais faire.
j'ai effectivement zappé le privé/public.
dans mon vrai code, tout est public, donc l'appel A(1) ne crée pas un objet dans le vide, et va bien initialiser A::a. J'ai bon ?
Yoxoman wrote:
A noter que, sous réserve de déclarer le constructeur de A public, A::a
vaut 0 après instanciation de B.
Cela vient du fait que dans
B(int m_b=0) {A(1);b=m_b;};
Le constructeur de A est appelé (avec sa valeur par défaut) avant même
d'entrer dans les accolades. A(1) crée un objet A dans le vide. Ce que
tu voulais faire est sûrement :
B(int m_b = 0) : A(1), b(m_b) {}
A::a vaut maintenant 1.
Oui c'est ça que je voulais faire.
j'ai effectivement zappé le privé/public.
dans mon vrai code, tout est public, donc l'appel A(1) ne crée pas un
objet dans le vide, et va bien initialiser A::a. J'ai bon ?
A noter que, sous réserve de déclarer le constructeur de A public, A::a vaut 0 après instanciation de B.
Cela vient du fait que dans
B(int m_b=0) {A(1);b=m_b;};
Le constructeur de A est appelé (avec sa valeur par défaut) avant même d'entrer dans les accolades. A(1) crée un objet A dans le vide. Ce que tu voulais faire est sûrement :
B(int m_b = 0) : A(1), b(m_b) {}
A::a vaut maintenant 1. Oui c'est ça que je voulais faire.
j'ai effectivement zappé le privé/public.
dans mon vrai code, tout est public, donc l'appel A(1) ne crée pas un objet dans le vide, et va bien initialiser A::a. J'ai bon ?
Yoxoman
B(int m_b = 0) : A(1), b(m_b) {}
A::a vaut maintenant 1. Oui c'est ça que je voulais faire.
j'ai effectivement zappé le privé/public.
dans mon vrai code, tout est public, donc l'appel A(1) ne crée pas un objet dans le vide, et va bien initialiser A::a. J'ai bon ?
Heu... Non.
En fait, la distinction privée/public ne t'apportera que des erreurs de compilation, pas de changement de comportement d'un programme. Ca concerne la visibilité des attributs/méthodes par d'autres méthodes.
Pour ton problème, quand une classe B dérive d'une classe A, la création d'une instance de B implique la création d'une instance de A, et ensuite la création du reste (dans B). Cela nécessite un appel constructeur pour A, puis un autre pour B. Ok. Par défaut, l'appel constructeur pour A est celui qui peut s'appeler sans paramètres. Dans ton cas, il s'agit de A(int), avec la valeur par défaut 0. Cependant, tu peux explicitement appeler un autre constructeur pour A : il suffit de le spécifier par la syntaxe que je t'ai indiqué, c'est-à-dire après les deux points, et avant les accolades. Il faut bien comprendre que dès que tu es à l'interieur des accolades dans la définition du constructeur de B, le mal est fait : l'objet A est construit, et le reste de B également. Plus rien n'est à construire, et donc tu n'appelles plus de constructeur pour ces objets. Tu peux par contre *modifier* des attributs, et faire tout ce que tu veux (peux) d'autre.
-- "Yo!" Martin Heidegger
B(int m_b = 0) : A(1), b(m_b) {}
A::a vaut maintenant 1.
Oui c'est ça que je voulais faire.
j'ai effectivement zappé le privé/public.
dans mon vrai code, tout est public, donc l'appel A(1) ne crée pas un
objet dans le vide, et va bien initialiser A::a. J'ai bon ?
Heu... Non.
En fait, la distinction privée/public ne t'apportera que des erreurs de
compilation, pas de changement de comportement d'un programme. Ca
concerne la visibilité des attributs/méthodes par d'autres méthodes.
Pour ton problème, quand une classe B dérive d'une classe A, la création
d'une instance de B implique la création d'une instance de A, et ensuite
la création du reste (dans B). Cela nécessite un appel constructeur pour
A, puis un autre pour B. Ok.
Par défaut, l'appel constructeur pour A est celui qui peut s'appeler
sans paramètres. Dans ton cas, il s'agit de A(int), avec la valeur par
défaut 0. Cependant, tu peux explicitement appeler un autre constructeur
pour A : il suffit de le spécifier par la syntaxe que je t'ai indiqué,
c'est-à-dire après les deux points, et avant les accolades.
Il faut bien comprendre que dès que tu es à l'interieur des accolades
dans la définition du constructeur de B, le mal est fait : l'objet A est
construit, et le reste de B également. Plus rien n'est à construire, et
donc tu n'appelles plus de constructeur pour ces objets. Tu peux par
contre *modifier* des attributs, et faire tout ce que tu veux (peux)
d'autre.
A::a vaut maintenant 1. Oui c'est ça que je voulais faire.
j'ai effectivement zappé le privé/public.
dans mon vrai code, tout est public, donc l'appel A(1) ne crée pas un objet dans le vide, et va bien initialiser A::a. J'ai bon ?
Heu... Non.
En fait, la distinction privée/public ne t'apportera que des erreurs de compilation, pas de changement de comportement d'un programme. Ca concerne la visibilité des attributs/méthodes par d'autres méthodes.
Pour ton problème, quand une classe B dérive d'une classe A, la création d'une instance de B implique la création d'une instance de A, et ensuite la création du reste (dans B). Cela nécessite un appel constructeur pour A, puis un autre pour B. Ok. Par défaut, l'appel constructeur pour A est celui qui peut s'appeler sans paramètres. Dans ton cas, il s'agit de A(int), avec la valeur par défaut 0. Cependant, tu peux explicitement appeler un autre constructeur pour A : il suffit de le spécifier par la syntaxe que je t'ai indiqué, c'est-à-dire après les deux points, et avant les accolades. Il faut bien comprendre que dès que tu es à l'interieur des accolades dans la définition du constructeur de B, le mal est fait : l'objet A est construit, et le reste de B également. Plus rien n'est à construire, et donc tu n'appelles plus de constructeur pour ces objets. Tu peux par contre *modifier* des attributs, et faire tout ce que tu veux (peux) d'autre.
-- "Yo!" Martin Heidegger
AG
Yoxoman wrote:
B(int m_b = 0) : A(1), b(m_b) {}
A::a vaut maintenant 1.
Oui c'est ça que je voulais faire.
j'ai effectivement zappé le privé/public.
dans mon vrai code, tout est public, donc l'appel A(1) ne crée pas un objet dans le vide, et va bien initialiser A::a. J'ai bon ?
Heu... Non.
En fait, la distinction privée/public ne t'apportera que des erreurs de compilation, pas de changement de comportement d'un programme. Ca concerne la visibilité des attributs/méthodes par d'autres méthodes.
Pour ton problème, quand une classe B dérive d'une classe A, la création d'une instance de B implique la création d'une instance de A, et ensuite la création du reste (dans B). Cela nécessite un appel constructeur pour A, puis un autre pour B. Ok. Par défaut, l'appel constructeur pour A est celui qui peut s'appeler sans paramètres. Dans ton cas, il s'agit de A(int), avec la valeur par défaut 0. Cependant, tu peux explicitement appeler un autre constructeur pour A : il suffit de le spécifier par la syntaxe que je t'ai indiqué, c'est-à-dire après les deux points, et avant les accolades. Il faut bien comprendre que dès que tu es à l'interieur des accolades dans la définition du constructeur de B, le mal est fait : l'objet A est construit, et le reste de B également. Plus rien n'est à construire, et donc tu n'appelles plus de constructeur pour ces objets. Tu peux par contre *modifier* des attributs, et faire tout ce que tu veux (peux) d'autre.
ok. Je crois que je ne me suis pas encore approprié la notion de
constructeur. Merci pour cette nième explication trés claire.
Yoxoman wrote:
B(int m_b = 0) : A(1), b(m_b) {}
A::a vaut maintenant 1.
Oui c'est ça que je voulais faire.
j'ai effectivement zappé le privé/public.
dans mon vrai code, tout est public, donc l'appel A(1) ne crée pas un
objet dans le vide, et va bien initialiser A::a. J'ai bon ?
Heu... Non.
En fait, la distinction privée/public ne t'apportera que des erreurs de
compilation, pas de changement de comportement d'un programme. Ca
concerne la visibilité des attributs/méthodes par d'autres méthodes.
Pour ton problème, quand une classe B dérive d'une classe A, la création
d'une instance de B implique la création d'une instance de A, et ensuite
la création du reste (dans B). Cela nécessite un appel constructeur pour
A, puis un autre pour B. Ok.
Par défaut, l'appel constructeur pour A est celui qui peut s'appeler
sans paramètres. Dans ton cas, il s'agit de A(int), avec la valeur par
défaut 0. Cependant, tu peux explicitement appeler un autre constructeur
pour A : il suffit de le spécifier par la syntaxe que je t'ai indiqué,
c'est-à-dire après les deux points, et avant les accolades.
Il faut bien comprendre que dès que tu es à l'interieur des accolades
dans la définition du constructeur de B, le mal est fait : l'objet A est
construit, et le reste de B également. Plus rien n'est à construire, et
donc tu n'appelles plus de constructeur pour ces objets. Tu peux par
contre *modifier* des attributs, et faire tout ce que tu veux (peux)
d'autre.
ok. Je crois que je ne me suis pas encore approprié la notion de
constructeur. Merci pour cette nième explication trés claire.
dans mon vrai code, tout est public, donc l'appel A(1) ne crée pas un objet dans le vide, et va bien initialiser A::a. J'ai bon ?
Heu... Non.
En fait, la distinction privée/public ne t'apportera que des erreurs de compilation, pas de changement de comportement d'un programme. Ca concerne la visibilité des attributs/méthodes par d'autres méthodes.
Pour ton problème, quand une classe B dérive d'une classe A, la création d'une instance de B implique la création d'une instance de A, et ensuite la création du reste (dans B). Cela nécessite un appel constructeur pour A, puis un autre pour B. Ok. Par défaut, l'appel constructeur pour A est celui qui peut s'appeler sans paramètres. Dans ton cas, il s'agit de A(int), avec la valeur par défaut 0. Cependant, tu peux explicitement appeler un autre constructeur pour A : il suffit de le spécifier par la syntaxe que je t'ai indiqué, c'est-à-dire après les deux points, et avant les accolades. Il faut bien comprendre que dès que tu es à l'interieur des accolades dans la définition du constructeur de B, le mal est fait : l'objet A est construit, et le reste de B également. Plus rien n'est à construire, et donc tu n'appelles plus de constructeur pour ces objets. Tu peux par contre *modifier* des attributs, et faire tout ce que tu veux (peux) d'autre.
ok. Je crois que je ne me suis pas encore approprié la notion de
constructeur. Merci pour cette nième explication trés claire.
kanze
Fabien LE LEZ wrote:
On 7 Nov 2005 23:44:41 -0800, "kanze" :
extern void f( int = 1, int ) ;
extern void f( int, int = 2 ) ;
Ce n'est pas autorisé, ça, si ?
À vrai dire, je ne suis plus sûr. Il me semble en avoir vu un exemple comme ça, mais en lisant la norme, j'ai plutôt l'impression qu'il faudrait inverser les deux déclarations (§8.3.6/4) : « In a given function declaration, all parameters subsequent to a parameter with a default argument shall have default arguments supplied in this or in previous declarations. »
En tout cas, extern void f( int, int = 2 ) ; extern void f( int = 1, int ) ; est légal.
Aussi :
extern void f( int = 1 ) ;
void g() { extern void f( int = 2 ) ; }
Dans g(), f a un paramètre par défaut de 2, ailleurs de 1.
Dans la pratique, évidemment, toute fonction doit être declarée exactement deux fois, une fois dans sa définition, dans un fichier source (ou dans l'en-tête, après sa declaration, dans le cas d'une fonction inline), et une (seule) declaration dans un fichier d'en-tête. Tous les paramètres par défaut seront sur la seule déclaration dans l'en-tête.
Évidemment, il serait impossible d'exiger quelque chose de pareil dans la norme -- les phases de compilation en prendrait un sacré coup, sans parler des questions de compatibilité avec C et les anciennes versions de C++.
-- James Kanze GABI Software Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Fabien LE LEZ wrote:
On 7 Nov 2005 23:44:41 -0800, "kanze" <kanze@gabi-soft.fr>:
extern void f( int = 1, int ) ;
extern void f( int, int = 2 ) ;
Ce n'est pas autorisé, ça, si ?
À vrai dire, je ne suis plus sûr. Il me semble en avoir vu un
exemple comme ça, mais en lisant la norme, j'ai plutôt
l'impression qu'il faudrait inverser les deux déclarations
(§8.3.6/4) : « In a given function declaration, all parameters
subsequent to a parameter with a default argument shall have
default arguments supplied in this or in previous
declarations. »
En tout cas,
extern void f( int, int = 2 ) ;
extern void f( int = 1, int ) ;
est légal.
Aussi :
extern void f( int = 1 ) ;
void
g()
{
extern void f( int = 2 ) ;
}
Dans g(), f a un paramètre par défaut de 2, ailleurs de 1.
Dans la pratique, évidemment, toute fonction doit être declarée
exactement deux fois, une fois dans sa définition, dans un
fichier source (ou dans l'en-tête, après sa declaration, dans le
cas d'une fonction inline), et une (seule) declaration dans un
fichier d'en-tête. Tous les paramètres par défaut seront sur la
seule déclaration dans l'en-tête.
Évidemment, il serait impossible d'exiger quelque chose de
pareil dans la norme -- les phases de compilation en prendrait
un sacré coup, sans parler des questions de compatibilité avec C
et les anciennes versions de C++.
--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
À vrai dire, je ne suis plus sûr. Il me semble en avoir vu un exemple comme ça, mais en lisant la norme, j'ai plutôt l'impression qu'il faudrait inverser les deux déclarations (§8.3.6/4) : « In a given function declaration, all parameters subsequent to a parameter with a default argument shall have default arguments supplied in this or in previous declarations. »
En tout cas, extern void f( int, int = 2 ) ; extern void f( int = 1, int ) ; est légal.
Aussi :
extern void f( int = 1 ) ;
void g() { extern void f( int = 2 ) ; }
Dans g(), f a un paramètre par défaut de 2, ailleurs de 1.
Dans la pratique, évidemment, toute fonction doit être declarée exactement deux fois, une fois dans sa définition, dans un fichier source (ou dans l'en-tête, après sa declaration, dans le cas d'une fonction inline), et une (seule) declaration dans un fichier d'en-tête. Tous les paramètres par défaut seront sur la seule déclaration dans l'en-tête.
Évidemment, il serait impossible d'exiger quelque chose de pareil dans la norme -- les phases de compilation en prendrait un sacré coup, sans parler des questions de compatibilité avec C et les anciennes versions de C++.
-- James Kanze GABI Software Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
kanze
Yoxoman wrote:
B(int m_b = 0) : A(1), b(m_b) {}
A::a vaut maintenant 1. Oui c'est ça que je voulais faire.
j'ai effectivement zappé le privé/public.
dans mon vrai code, tout est public, donc l'appel A(1) ne crée pas un objet dans le vide, et va bien initialiser A::a. J'ai bon ?
Heu... Non.
En fait, la distinction privée/public ne t'apportera que des erreurs de compilation, pas de changement de comportement d'un programme. Ca concerne la visibilité des attributs/méthodes par d'autres méthodes.
Just un détail du langage, mais tu te contradis là. Justement, en C++ les contrôles d'accès (public, private) ne concerne pas la visibilité -- un symbole est *visible* qu'il soit privé ou non. Le compilateur fait tout ce qu'il doit faire : name binding, résolution du surcharge, etc., sans prendre l'accès en considération. Seulement, si après tout ça, il s'avère que tu as essayé d'utiliser un symbole dont tu n'as pas le droit, tu as une erreur.
-- James Kanze GABI Software Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Yoxoman wrote:
B(int m_b = 0) : A(1), b(m_b) {}
A::a vaut maintenant 1.
Oui c'est ça que je voulais faire.
j'ai effectivement zappé le privé/public.
dans mon vrai code, tout est public, donc l'appel A(1) ne
crée pas un objet dans le vide, et va bien initialiser A::a.
J'ai bon ?
Heu... Non.
En fait, la distinction privée/public ne t'apportera que des
erreurs de compilation, pas de changement de comportement d'un
programme. Ca concerne la visibilité des attributs/méthodes
par d'autres méthodes.
Just un détail du langage, mais tu te contradis là. Justement,
en C++ les contrôles d'accès (public, private) ne concerne pas
la visibilité -- un symbole est *visible* qu'il soit privé ou
non. Le compilateur fait tout ce qu'il doit faire : name
binding, résolution du surcharge, etc., sans prendre l'accès en
considération. Seulement, si après tout ça, il s'avère que tu as
essayé d'utiliser un symbole dont tu n'as pas le droit, tu as
une erreur.
--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
A::a vaut maintenant 1. Oui c'est ça que je voulais faire.
j'ai effectivement zappé le privé/public.
dans mon vrai code, tout est public, donc l'appel A(1) ne crée pas un objet dans le vide, et va bien initialiser A::a. J'ai bon ?
Heu... Non.
En fait, la distinction privée/public ne t'apportera que des erreurs de compilation, pas de changement de comportement d'un programme. Ca concerne la visibilité des attributs/méthodes par d'autres méthodes.
Just un détail du langage, mais tu te contradis là. Justement, en C++ les contrôles d'accès (public, private) ne concerne pas la visibilité -- un symbole est *visible* qu'il soit privé ou non. Le compilateur fait tout ce qu'il doit faire : name binding, résolution du surcharge, etc., sans prendre l'accès en considération. Seulement, si après tout ça, il s'avère que tu as essayé d'utiliser un symbole dont tu n'as pas le droit, tu as une erreur.
-- James Kanze GABI Software Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34