OVH Cloud OVH Cloud

Classe template et instances

9 réponses
Avatar
Nico
Bonjour,


J'ai un petit problème avec une classe template "Matrice<T>" que je suis
en train de coder.

Imaginons une méthode 'Inverse()' de la classe Matrice<T>, qui retourne
une Matrice<double> inverse de M1<T> avec T pas forcément double.

Le probleme apparait lorsque j'utilise la matrice qui va être retournée
par Inverse() dans la fonction.

Matrice<double> Mretour(n,n); //declaration acceptee dans Inverse()

Mretour.tableau[i][j]; //erreur, 'a' is private within this context.


Voilà, je ne comprend pas, on dirait que le compilateur considère que
Mretour n'est pas de la meme classe que this, comme s'il considérait
chaque instance de la classe template comme une classe template différente.

Il se passe exactement la meme chose dans des fonctions amies de
Matrice<T>, elles sont incapable de "voir" les membres privés de
matrices dont le type a été spécifié.

Quelle est la solution ?


Merci

Nico

9 réponses

Avatar
Franck Branjonneau
Nico écrivait:

J'ai un petit problème avec une classe template "Matrice<T>" que je
suis en train de coder.

Imaginons une méthode 'Inverse()'


Point de méthode en C++, des fonctions membres.

de la classe Matrice<T>, qui retourne une Matrice<double> inverse de
M1<T> avec T pas forcément double.

Le probleme apparait lorsque j'utilise la matrice qui va être
retournée par Inverse() dans la fonction.


*La* fonction ?

Matrice<double> Mretour(n,n); //declaration acceptee dans Inverse()


Ce n'est pas plutôt une définition ?

Mretour.tableau[i][j]; //erreur, 'a' is private within this
context.


"Context" qui nous est inconnu.

Quelle est la solution ?


Poster un code compilable -- à tout le moins pour la partie ne
concernant pas ta question -- illustrant le problème.

--
Franck Branjonneau

Avatar
James Kanze
On Feb 25, 2:07 pm, Nico wrote:

J'ai un petit problème avec une classe template "Matrice<T>" que je suis
en train de coder.

Imaginons une méthode 'Inverse()' de la classe Matrice<T>, qui retourne
une Matrice<double> inverse de M1<T> avec T pas forcément double.

Le probleme apparait lorsque j'utilise la matrice qui va être retourn ée
par Inverse() dans la fonction.

Matrice<double> Mretour(n,n); //declaration acceptee dans Inverse()

Mretour.tableau[i][j]; //erreur, 'a' is private within this context.

Voilà, je ne comprend pas, on dirait que le compilateur considère que
Mretour n'est pas de la meme classe que this, comme s'il considérait
chaque instance de la classe template comme une classe template différe nte.


Comme Franck, je ne vois pas trop ce que tu essaies de faire, ni
où tu as réelement un problème, mais une chose est certaine :
chaque instantiation différente d'un template de classe est une
classe différente. Et qu'un Matrice<float> n'a pas plus d'accès
aux données privées d'un Matrice<double> que n'en a une classe
Toto quelconque.

Il se passe exactement la meme chose dans des fonctions amies de
Matrice<T>, elles sont incapable de "voir" les membres privés de
matrices dont le type a été spécifié.


Les amis de Matrice<double> sont des amis de Matrice<float>,
non les amis de Matrice<double>.

Quelle est la solution ?


Quel est le problème ?

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

Avatar
Cyrille

Les amis de Matrice<double> sont des amis de Matrice<float>,
non les amis de Matrice<double>.


??

--
http://www.voteragauche.org/

Avatar
Nico

Imaginons une méthode 'Inverse()'


Point de méthode en C++, des fonctions membres.


Bonjour Franck,




Poster un code compilable -- à tout le moins pour la partie ne
concernant pas ta question -- illustrant le problème.






using namespace std;
#include <iostream>


template<typename T>
classe MaClasse
{

private:
T membre;

public:
MaClasse(){cout << "construction" << endl;}
MaClasse<double> Fn1();

};



template <typename T>
MaClasse<double>
MaClasse<T>::Fn1()
{
MaClasse<double> mc; //ici classe de DOUBLE
mc.membre = 2;

return mc;
}



int main()
{

MaClasse<int> mc1; //Donc T=int

mc1.Fn1();

return 0;
}





compilateur :

in member function'MaClass<double> MaClasse<T>::Fn1() [with T = int]
error : 'double MaClasse<double>::membre' is private




si maintenant je fais le main suivant :


int main()
{

MaClasse<double> mc1; //Donc T=double

mc1.Fn1();

return 0;
}


ça compile sans problème...
Donc tout se passe comme si Fn1 ne connaissait pas les membres des
classes dont le paramètre template T n'est pas égal au type de 'mc'

Donc ce que je disais c'est qu'on dirait que les instanciations
différentes de classes templates sont comme des classes différentes, ce
qui expliquerait que Fn1, instanciée depuis une MaClasse<int> ne puisse
pas accéder à des membres de MaClasse<double>

Comment remédier à ce problème ?

Merci

Nico


Avatar
Nico

mais une chose est certaine :
chaque instantiation différente d'un template de classe est une
classe différente. Et qu'un Matrice<float> n'a pas plus d'accès
aux données privées d'un Matrice<double> que n'en a une classe
Toto quelconque.



Ok c'est bien ce que ça laissait supposer.... Ma 'solution'était de
déclarer toutes les spécialisations de MaClasse<T> comme amies "les unes
des autres", mais j'ai pas du tout réussi à faire ça :s

L'autre solution, vraiment lourdingue, est d'utiliser des accesseurs
dans les fonctions membres... j'aimerais mieux ne pas avoir reccours à
ça car pour des classes avec beaucoup de membres privés ça complique
vraiment inutilement le code.

Merci

Nico

Avatar
Franck Branjonneau
Nico écrivait:


Poster un code compilable -- à tout le moins pour la partie ne
concernant pas ta question -- illustrant le problème.


template<typename T>
classe MaClasse


J'ait dit compilable. ;-)

{

private:
T membre;

public:
MaClasse(){cout << "construction" << endl;}
MaClasse<double> Fn1();

};



template <typename T>
MaClasse<double>
MaClasse<T>::Fn1()
{
MaClasse<double> mc; //ici classe de DOUBLE
mc.membre = 2;

return mc;
}



int main()
{

MaClasse<int> mc1; //Donc T=int

mc1.Fn1();

return 0;
}





compilateur :

in member function'MaClass<double> MaClasse<T>::Fn1() [with T = int]
error : 'double MaClasse<double>::membre' is private

Donc tout se passe comme si Fn1 ne connaissait pas les membres des
classes dont le paramètre template T n'est pas égal au type de 'mc'


Exact.

Donc ce que je disais c'est qu'on dirait que les instanciations
différentes de classes templates sont comme des classes différentes,
ce qui expliquerait que Fn1, instanciée depuis une MaClasse<int> ne
puisse pas accéder à des membres de MaClasse<double>


Oui.

Comment remédier à ce problème ?


Utilise friend :

template<typename T>
class MaClasse
{

template< typename U >
friend MaClasse<double> MaClasse< U >::Fn1();

//...

};

qui se lit quelque soit (T,U) MaClasse< U >::Fn1() est autorisé à
accéder aux membres de MaClasse< T >. Si c'est trop large, il te faut
spécialiser explicitement MaClasse< double > :

template<>
class MaClasse< double >
{

template< typename U >
friend MaClasse<double> MaClasse< U >::Fn1();

// ...
};

qui se lit quelque soit U MaClasse< double >::Fn1() est autorisé à
accéder aux membres de MaClasse< U >.

--
Boujou t'chu tè.
Franck Branjonneau


Avatar
Mathias Gaunard

Voilà, je ne comprend pas, on dirait que le compilateur considère que
Mretour n'est pas de la meme classe que this, comme s'il considérait
chaque instance de la classe template comme une classe template différente.


Ton message est assez cryptique, mais ce que tu dis là laisse supposer
que tu penses que toutes les instances d'un template sont d'un même type.
C'est bien évidemment faux, chaque instance de template créé un type
différent, c'est justement le principe du truc.

Avatar
James Kanze
On Feb 25, 4:20 pm, Cyrille wrote:

Les amis de Matrice<double> sont des amis de Matrice<float>,
non les amis de Matrice<double>.


??


Ça aurait dû être « Les amis de Matrice<double> sont des amis
de Matrice<double, et non les amis de Matrice<float> »,
évidemment.

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


Avatar
Nico

Ton message est assez cryptique, mais ce que tu dis là laisse supposer
que tu penses que toutes les instances d'un template sont d'un même type.
C'est bien évidemment faux, chaque instance de template créé un type
différent, c'est justement le principe du truc.



salut,

ok j'aurais dû dire spécialisation au lieu d'instance je pense.