Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Acces objets membres d'une classe template parente...

4 réponses
Avatar
TjB
Bonjour,

J'ai un petit souci li=E9 =E0 l'acc=E8s =E0 des objets membres d'une
classe template parente (si la classe n'est pas template, il n'y a pas
de probl=E8me, un peu comme d'habitude...).

Soit la d=E9finition des classes A et Z :
//-----------------------------------
template <class T> class A {
public:
T a;
};

template <class T>
class Z : public A<T> {
public:
Z() { a=3D3; }
~Z() { }
};
//---------------------------------------------------------------

Avec un main() instantiant un objet de classe Z, on obtient avec g++
une erreur :
In constructor 'Z<T>::Z()':
error: 'a' was not declared in this scope

Pour que le code compile, il faut =E9crire le constructeur de Z() :

Z() { this->a =3D 3 }

ou bien

Z() { A<T>::a =3D 3 }

Alors deux questions :

1) Quelqu'un voit-il une bonne raison =E0 ce fonctionnement ?
2) Quelqu'un conna=EEt-il une astuce (genre option de compilation ou
autre) pour conserver la premi=E8re notation ?

Merci !

T=2E

---
Tristan Beau http://www.apc.univ-paris7.fr/~beau/
AstroParticules et Cosmologie

4 réponses

Avatar
meow
CF le fil de discussion que j'ai ouvert 3 coups avant toi :D
J'ai moi aussi expérimenté ce genre de trucs, et il m'a semblé que
le comportement dépendait de la version de gcc ! genre, avant mise à
jour de ma debian ça marchait sans problème, et depuis il a des
ratés...
Avatar
kanze
TjB wrote:

J'ai un petit souci lié à l'accès à des objets membres d'une
classe template parente (si la classe n'est pas template, il
n'y a pas de problème, un peu comme d'habitude...).

Soit la définition des classes A et Z :
//-----------------------------------
template <class T> class A {
public:
T a;
};

template <class T>
class Z : public A<T> {
public:
Z() { a=3; }
~Z() { }
};
//---------------------------------------------------------------

Avec un main() instantiant un objet de classe Z, on obtient
avec g++ une erreur :


Avec une version récente de g++. Avec 2.95.2, par exemple, ça
passe.

In constructor 'Z<T>::Z()':
error: 'a' was not declared in this scope

Pour que le code compile, il faut écrire le constructeur de Z() :

Z() { this->a = 3 }

ou bien

Z() { A<T>::a = 3 }

Alors deux questions :

1) Quelqu'un voit-il une bonne raison à ce fonctionnement ?


C'est ce que la norme du langage exige. J'ai expliqué quelque
détails de ce que dit la norme dans un autre fil ; le mieux,
quand même, c'est de se procurer le Josuttis et Vandevoorde, et
le lire soigneusement. (J'ajouterais que c'est très bien écrit,
et assez facile à lire, même s'il traite un sujet plutôt
complexe.)

2) Quelqu'un connaît-il une astuce (genre option de compilation ou
autre) pour conserver la première notation ?


Utiliser un ancien compilateur. Ça passe avec g++ 2.95.2, Sun CC
4.2 et VC++ 6.0.

Évidemment, une telle solution comporte d'autres problèmes:-).

--
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

Avatar
TjB
Si c'est dans la norme, je vais faire un effort dans le code, c'est
tout de même la meilleure solution pour l'avenir.

Mais en deux mots, quel est l' "esprit" de la norme qui fait que
l'accès à ces membres de classe template parente est impossible de
manière directe ?

T.
---
Tristan Beau http://www.apc.univ-paris7.fr/~beau/
AstroParticules et Cosmologie
Avatar
kanze
TjB wrote:
Si c'est dans la norme, je vais faire un effort dans le code,
c'est tout de même la meilleure solution pour l'avenir.

Mais en deux mots, quel est l' "esprit" de la norme qui fait
que l'accès à ces membres de classe template parente est
impossible de manière directe ?


Deux choses : d'une part, le but, c'est de permettre au
compilateur de detecter les plus d'erreurs possibles le plus tôt
possibles, et donc de pouvoir parser le template dès sa
définition, sans attendre une instantiation. L'autre, c'est
qu'on veut bien éviter le détournement des noms dans le
template, c-à-d que si j'écris sin(x) dans un template, avec
l'intention d'utiliser le ::sin() de <math.h>, je ne me rétrouve
pas avec une fonction sin() de la classe de base (ou d'ailleurs)
qui n'était présente que lors de l'instantiation, et que je
n'avais pas prévu.

On peut ne pas être d'accord avec la nécessité de ces démarches,
ou avec la façon que les deux problèmes ont été résolus, mais
c'est comme ça ; ça ne va pas changer maintenant. (Au moins, je
l'espère.)

En ce qui concerne l'« invisibilité » de la classe de base, elle
s'écoule de la solution adoptée. Et ça ne m'étonnerait pas que
même les auteurs de cette solution la considèrent comme une
conséquence regrettable, plutôt que quelque chose désirable en
soi. Mais il faut considérer l'ensemble -- comme j'ai dit, on
peut ne pas être d'accord sur les principes de base, mais il
faut reconnaître une certaine cohérence dans leur
implémentation : une fois qu'on a décidé 1) qu'il faut
distinguer entre les noms dépendants et les noms non-dépendants
(pour éviter le détournement), et 2) qu'il ne faut pas que
l'utilisateur soit obligé à declarer explicitement lequel et
lequel, c'est difficile de faire mieux.

--
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