Héritage et constructeur

Le
AG
Bonjour,

soit le code suivant :

class A
{
int debut;
int fin;
A(int a, int b){debut=1;fin=2;};
};

class B : public A
{
B(int a, int b):A::A(a,b){};
};

Mon compilo Visual C++ bloque sur B(int a, int b): A::A(a,b) {};

il lui faut : B(int a, int b): A(a,b) {};

Est-ce vraiment une erreur ? gcc ne dit pas qu'il s'agit d'une erreur.

AG.
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
Fabien LE LEZ
Le #306799
On Wed, 2 May 2007 19:21:33 +0200, "AG"
Mon compilo Visual C++ bloque sur B(int a, int b): A::A(a,b) {};

Est-ce vraiment une erreur ?


Je ne suis pas totalement sûr qu'il s'agisse d'une erreur, mais c'est
très certainement une incongruité.

Alain Gaillard
Le #306773
Je ne suis pas totalement sûr qu'il s'agisse d'une erreur,


Je n'en suis pas sûr non plus. Mais une fois n'est pas coutume, je
donnerais raison à Visual :)

mais c'est
très certainement une incongruité.


C'est le moins que l'on puisse dire.
Pourquoi utiliser l'opérateur de résolution de portée dans

B(int a, int b): A::A(a,b) {};

Ca n'a pas de sens. Parce qu'il n'existe pas de constructeur virtuel alors
quand on écrit normalement

B(int a, int b): A(a,b) {};

on est sûr que c'est bien le constructeur de A qui est appelé.

Est-ce une erreur ? la question serait plutôt, est-ce qu'en
programmation faire un pléonasme est une erreur ou pas ? ;)


--
Alain

Alain Gaillard
Le #306772
Je ne suis pas totalement sûr qu'il s'agisse d'une erreur,


Je n'en suis pas sûr non plus. Mais une fois n'est pas coutume, je
donnerais raison à Visual :)

mais c'est
très certainement une incongruité.


C'est le moins que l'on puisse dire.
Pourquoi utiliser l'opérateur de résolution de portée dans

B(int a, int b): A::A(a,b) {};

Ca n'a pas de sens. Parce qu'il n'existe pas de constructeur virtuel alors
quand on écrit normalement

B(int a, int b): A(a,b) {};

on est sûr que c'est bien le constructeur de A qui est appelé.
D'autant plus qu'il n'y a pas d'instance de A existante à ce stade :)

Est-ce une erreur ? la question serait plutôt, est-ce qu'en
programmation faire un pléonasme est une erreur ou pas ? ;)

Fabien LE LEZ
Le #306771
On Thu, 03 May 2007 11:15:02 +0200, Alain Gaillard

Est-ce une erreur ? la question serait plutôt, est-ce qu'en
programmation faire un pléonasme est une erreur ou pas ? ;)


Il me semble qu'employer inutilement une façon différente de la
méthode habituelle, est une erreur en soi, puisqu'elle rend la
relecture plus difficile.

James Kanze
Le #306769
On May 3, 11:15 am, Alain Gaillard wrote:
Je ne suis pas totalement sûr qu'il s'agisse d'une erreur,


Je n'en suis pas sûr non plus. Mais une fois n'est pas coutume, je
donnerais raison à Visual :)


Je ne suis pas sûr. Le nom de la classe est injectée dans la
classe -- si j'écris donc A::A, on va chercher A dans A, et
puisque le nom y est, on le retrouve. Et ainsi de suite : A,
A::A, A::A::A, A::A::A::A... signifie tous la même chose, la
classe A.

Sauf que, évidemment, dans certains contextes, A::A signifie le
constructeur d'A. Seulement, la norme est on ne peut plus
imprécise sur ce sujet. Tout ce qu'elle dit, c'est :

Constructors do not have names. A special declarator
syntax using an optional sequence of function-specifiers
followed by the constructor's class name followed by a
parameter list is used to declare or define the
constructor.

Seulement, personne n'implémente ça tel qu'il est écrit ; pris
à la lettre, ça signifierait que :

class C { public : C() ; } ;

C() // Nom de la classe !!!
{
}

serait légal (or qu'aucun compilateur, à ma connaissance, ne
l'accepte). Je crois plutôt que c'est seulement quand le nom de
la classe apparaît dans la portée de la classe qu'il peut être
pris comme constructeur. Mais alors, encore... est-ce que ça
vaut partout ou non ? Et selon quels critères est-ce qu'il faut
décider si () est un « parameter list » ou un « argument
list » ?

Je crois que dans ce cas précis, la norme est assez claire :

mem-initializer-id:
::[opt] nested-name-specifier[opt] class-name

La seule interprétation permise par la grammaire, c'est que le
premier A, c'est un nested-name-specifier, et que le deuxième,
c'est un class-name. C'est donc légal. Mais la situation décrite
ci-dessus me semble assez vague que je ne critiquerais pas trop
un compilateur qui interprète A::A(... comme un essai de
déclarer un constructeur (ce qui n'est évidemment pas permis
ici).

mais c'est
très certainement une incongruité.


C'est le moins que l'on puisse dire.
Pourquoi utiliser l'opérateur de résolution de portée dans

B(int a, int b): A::A(a,b) {};

Ca n'a pas de sens. Parce qu'il n'existe pas de constructeur virtuel alors
quand on écrit normalement

B(int a, int b): A(a,b) {};

on est sûr que c'est bien le constructeur de A qui est appelé.


C'est toujours le constructeur de A qu'on appelle. Ce n'est pas
lui qu'on nomme ; on nomme la classe de base.

Est-ce une erreur ? la question serait plutôt, est-ce qu'en
programmation faire un pléonasme est une erreur ou pas ? ;)


Disons que c'est une erreur, dans le sens plus général. Même si
le langage le permet, ça déroute, et ça sème la confusion. Et
où je travaille, on considère le code qui déroute et qui sème la
confusion d'être en erreur aussi. Même si le compilateur ne le
rejette pas, la revue de code, elle, le rejettera.

--
James Kanze (GABI Software) email:
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


Alain Gaillard
Le #306767
on est sûr que c'est bien le constructeur de A qui est appelé.


C'est toujours le constructeur de A qu'on appelle. Ce n'est pas
lui qu'on nomme ; on nomme la classe de base.


Tout à fait.

confusion d'être en erreur aussi. Même si le compilateur ne le
rejette pas, la revue de code, elle, le rejettera.


Je crois que nous sommes tous d'accord là dessus.


--
Alain


Publicité
Poster une réponse
Anonyme