C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

template operator= et héritage
Goto page 1, 2  Next
 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (French)
View previous topic :: View next topic  
Author Message
Mathieu Peyréga
Guest





PostPosted: Thu Sep 25, 2003 8:24 pm    Post subject: template operator= et héritage Reply with quote



Bonsoir, que ce soit avec VC++ ou gcc, le code suivant ne compile pas
(ou plus exactement ne linke pas...)
est-ce un non respect de la norme ou de la syntaxe de ma part ou un
défaut d'implémentation des compilos ?

cordialement,

MP


#include <iostream>

//************************ classe de base ********************************
template <class T>
class ISeq
{
public:

virtual ~ISeq(void) = 0;
virtual ISeq<T>& operator=(ISeq<T> const& obj) = 0;

virtual void setValue(T const& value) = 0;
virtual T const& getValue(void) const = 0;
};

template <class T>
ISeq<T>::~ISeq<T>(void)
{
}

//************************ classe de base ********************************

template <class T>
class IUSeq : public virtual ISeq<T>
{
public:
virtual ~IUSeq(void) = 0;
};

template <class T>
IUSeq<T>::~IUSeq<T>(void)
{
}

//************************ implémentation 1 ********************************
template <class T>
class Seq1 : public virtual ISeq<T>
{
public:

Seq1(void);
~Seq1(void);

ISeq<T>& operator=(ISeq<T> const& obj);

void setValue(T const& value) { m_value = value; }
T const& getValue(void) const { return m_value; }

protected:

T m_value;
};

//************************ implémentation 2 ********************************
template <class T>
class Seq2 : public IUSeq<T>, public virtual Seq1<T>
{
public:

Seq2(void);
~Seq2(void);

ISeq<T>& operator=(ISeq<T> const& obj);
};


template <class T>
Seq1<T>::Seq1(void)
{
}

template <class T>
Seq1<T>::~Seq1(void)
{
}

template <class T>
Seq2<T>::Seq2(void)
{
}

template <class T>
Seq2<T>::~Seq2(void)
{
}

template <class T>
ISeq<T>& Seq1<T>::operator=(ISeq<T> const& obj)
{
std::cout << "Seq1::operator=" << std::endl;
setValue(obj.getValue());
return *this;
}

template ISeq<T>& Seq2<T>::operator=(ISeq<T> const& obj)
{
std::cout << "Seq2::operator=" << std::endl;
setValue(obj.getValue());
return *this;
}

int main(int argc, char* argv[])
{

Seq1 Seq2<double> *pB = new Seq2<double>;

ISeq<double> *pIA = pA;
ISeq<double> *pIB = pB;

pA->setValue(1.0);
pB->setValue(2.0);
std::cout << "A : " << pA->getValue() << " B : " << pB->getValue() <<
std::endl;
std::cout << "A = B" << std::endl;
*pA = *pB;
std::cout << "A : " << pA->getValue() << " B : " << pB->getValue() <<
std::endl;

pA->setValue(1.0);
pB->setValue(2.0);
std::cout << "A : " << pA->getValue() << " B : " << pB->getValue() <<
std::endl;
std::cout << "B = A" << std::endl;
*pB = *pA;
std::cout << "A : " << pA->getValue() << " B : " << pB->getValue() <<
std::endl;

system("PAUSE");
return 0;
}

Back to top
kanze@gabi-soft.fr
Guest





PostPosted: Fri Sep 26, 2003 7:30 am    Post subject: Re: template operator= et héritage Reply with quote



Mathieu Peyréga <peyrega (AT) no (DOT) spam.please.netcourrier.com> wrote in
message news:<3F734EEF.1010206 (AT) no (DOT) spam.please.netcourrier.com>...

Quote:
Bonsoir, que ce soit avec VC++ ou gcc, le code suivant ne compile pas
(ou plus exactement ne linke pas...)

Ç'aurait été plus gentil si tu nous avais indiqué de quoi ils se
plaignaient.

Quote:
est-ce un non respect de la norme ou de la syntaxe de ma part ou un
défaut d'implémentation des compilos ?

Je ne sais pas si c'est peut-être un problème de copier/coller, mais il
manque bien une implémentation de l'opérateur d'affectation dans ISeq.
Or dans Seq2, tu as deux opérateurs d'affectation, celui que tu as
déclaré, et l'opérateur d'affectation de copie, déclarée :
ISeq1& operator=( ISeq1 const& ) ;
implicitement par le compilateur.

Quand tu fais « *pA = *pB », tu affectes un Seq2 à un Seq1. Le
compilateur résoud le surcharge en faveur de l'affectation par copie
(Seq1 étant une base de Seq2), et essaie donc de générer une
implémentation implicitement aussi. Et c'est là que le bat blesse -- la
version générée appelle les opérateurs d'affectation des classes de
base.

Enfin, un commentaire plus général : la virtualité et l'affectation font
mauvais menage. En fait, on ne peut pas changer le type de l'objet dans
l'affectation. Le plus souvent, on préfère donc ne travailler qu'avec
des pointeurs, et d'utiliser une fonction « clone »

--
James Kanze GABI Software mailto:kanze (AT) gabi-soft (DOT) fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16

Back to top
DG
Guest





PostPosted: Fri Sep 26, 2003 8:07 am    Post subject: Re: template operator= et héritage Reply with quote



[email]kanze (AT) gabi-soft (DOT) fr[/email] writes:

Quote:
[...]

Quand tu fais « *pA = *pB », tu affectes un Seq2 à un Seq1. Le
compilateur résoud le surcharge en faveur de l'affectation par copie
(Seq1 étant une base de Seq2), et essaie donc de générer une
implémentation implicitement aussi. Et c'est là que le bat blesse -- la
version générée appelle les opérateurs d'affectation des classes de
base.

Pour ma part, j'ai un peu de mal à comprendre là. Si je t'ai bien suivi,
le compilateur génère implicitement l'implémentation suivante:
ISeq1& operator=( ISeq1 const& );

et c'est cette implémentation qui est utilisée lors du « *pA = *pB »
alors pourquoi a-t-on aussi besoin de d'une implémentation de
l'opérateur d'affectation dans les classes de bases ? Est-ce que c'est
le même mécanisme que lorsqu'une classe B hérite d'une classe A, lors
de l'instanciation d'un objet de type B, la constructeur de A puis
celui de B est appelé ?

Back to top
Christophe de Vienne
Guest





PostPosted: Fri Sep 26, 2003 9:04 am    Post subject: Re: template operator= et héritage Reply with quote

Mathieu Peyréga wrote:

Quote:
Bonsoir, que ce soit avec VC++ ou gcc, le code suivant ne compile pas
(ou plus exactement ne linke pas...)
est-ce un non respect de la norme ou de la syntaxe de ma part ou un
défaut d'implémentation des compilos ?

[...]
//************************ classe de base ********************************
template class ISeq
{
public:

virtual ~ISeq(void) = 0;

Il me semble que les destructeurs doivent forcément avoir une
implémentation, même si on ajoute '= 0' à la définition.


[...]
Quote:
Seq1(void);
~Seq1(void);
[...]
Seq2(void);
~Seq2(void);

Ou as-tu implémenté ces fonctions ? L'erreur au link ne serait pas qu'il
manque les fonctions SeqX::SeqX et SeqX::~SeqX ?

A+

Christophe

--
Christophe de Vienne
Experience is something you don't get until just after you need it.
Oliver's Law.

Back to top
Christophe de Vienne
Guest





PostPosted: Fri Sep 26, 2003 9:06 am    Post subject: Re: template operator= et héritage Reply with quote

Mathieu Peyréga wrote:

Quote:
Bonsoir, que ce soit avec VC++ ou gcc, le code suivant ne compile pas
(ou plus exactement ne linke pas...)

Pourrais-tu être plus précis : quels sont les messages du linker ?

A+

Christophe

--
Christophe de Vienne
Experience is something you don't get until just after you need it.
Oliver's Law.

Back to top
Mathieu Peyréga
Guest





PostPosted: Fri Sep 26, 2003 9:42 am    Post subject: Re: template operator= et héritage Reply with quote

Quote:
Il me semble que les destructeurs doivent forcément avoir une
implémentation, même si on ajoute '= 0' à la définition.

Ou as-tu implémenté ces fonctions ? L'erreur au link ne serait pas qu'il
manque les fonctions SeqX::SeqX et SeqX::~SeqX ?

A+

Christophe

c'est le cas... il sont implémentés si tu regardes le code fourni
l'erreur se produit au link et est relative à la première instruction
d'affectation du main

--
0% de pub! Que du bonheur et des vrais adhérents !
Vous aussi inscrivez-vous sans plus tarder!!
Message posté à partir de http://www.gyptis.org, BBS actif depuis 1995.




Back to top
Mathieu Peyréga
Guest





PostPosted: Fri Sep 26, 2003 9:45 am    Post subject: Re: template operator= et héritage Reply with quote

Quote:
Ç'aurait été plus gentil si tu nous avais indiqué de quoi ils se
plaignaient.

erreur de link (unresolved sur l'opérateur ISeq::operator=)

Quote:
Je ne sais pas si c'est peut-être un problème de copier/coller, mais il
manque bien une implémentation de l'opérateur d'affectation dans ISeq.

c'est volontaire puisque c'est une classe d'interface et que l'opérateur
est déclaré virtuel (autorisé par la norme pour l'opérateur =)
Les implémentations sont respectivement dans Seq1 et Seq2 qui sont bien
les classes concrètes instanciées

Quote:
Or dans Seq2, tu as deux opérateurs d'affectation, celui que tu as
déclaré, et l'opérateur d'affectation de copie, déclarée :
ISeq1& operator=( ISeq1 const& ) ;
implicitement par le compilateur.

Et qui ne fonctionne donc pas correctement puisqu'il apelle la mauvaise
implémentation...

Quote:
Quand tu fais « *pA = *pB », tu affectes un Seq2 à un Seq1. Le
compilateur résoud le surcharge en faveur de l'affectation par copie
(Seq1 étant une base de Seq2), et essaie donc de générer une
implémentation implicitement aussi. Et c'est là que le bat blesse -- la
version générée appelle les opérateurs d'affectation des classes de
base.

Enfin, un commentaire plus général : la virtualité et l'affectation font
mauvais menage. En fait, on ne peut pas changer le type de l'objet dans
l'affectation. Le plus souvent, on préfère donc ne travailler qu'avec
des pointeurs, et d'utiliser une fonction « clone »

ça pour faire mauvais ménage...
--
0% de pub! Que du bonheur et des vrais adhérents !
Vous aussi inscrivez-vous sans plus tarder!!
Message posté à partir de http://www.gyptis.org, BBS actif depuis 1995.




Back to top
Laurent DELEPINE
Guest





PostPosted: Fri Sep 26, 2003 9:46 am    Post subject: Re: template operator= et héritage Reply with quote

Mathieu Peyréga wrote:

Quote:
template <class T
class ISeq
{
public:

virtual ~ISeq(void) = 0;

C'est correct un destructeur virtuel pur ?

Quote:
template ISeq {
}

Surtout defini un peu plus loin.

A+

LD


Back to top
Jean-Marc Bourguet
Guest





PostPosted: Fri Sep 26, 2003 9:52 am    Post subject: Re: template operator= et héritage Reply with quote

Laurent DELEPINE <newsgroup (AT) webiologie (DOT) org> writes:

Quote:
Mathieu Peyréga wrote:

template <class T
class ISeq
{
public:
virtual ~ISeq(void) = 0;

C'est correct un destructeur virtuel pur ?

Oui ca force les descendants a le redefinir.

Quote:
template ISeq {
}

Surtout defini un peu plus loin.

Rien n'empeche de definir un membre pur, c'est meme obligatoire pour
le destructeur.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org

Back to top
Mathieu Peyréga
Guest





PostPosted: Fri Sep 26, 2003 11:35 am    Post subject: Re: template operator= et héritage Reply with quote

Quote:
virtual ~ISeq(void) = 0;
C'est correct un destructeur virtuel pur ?

c'est autorisé par la norme

Quote:
Surtout defini un peu plus loin.

et l'implémentation doit exister si on veut pouvoir instancier des classes
dérivées
--
0% de pub! Que du bonheur et des vrais adhérents !
Vous aussi inscrivez-vous sans plus tarder!!
Message posté à partir de http://www.gyptis.org, BBS actif depuis 1995.




Back to top
Mathieu Peyréga
Guest





PostPosted: Fri Sep 26, 2003 11:36 am    Post subject: Re: template operator= et héritage Reply with quote

Christophe de Vienne wrote:

Quote:
Mathieu Peyréga wrote:

Bonsoir, que ce soit avec VC++ ou gcc, le code suivant ne compile pas
(ou plus exactement ne linke pas...)

Pourrais-tu être plus précis : quels sont les messages du linker ?

g++.exe main.o -o "test.exe" -L"D:/Program_Files/Dev-Cpp/lib"
main.o(.text$_ZN4Seq1IdEaSERKS0_+0x1e):main.cpp: undefined reference to
`ISeq<double>::operator=(ISeq<double> const&)'

Compiling...
Main_test.cpp
d:projetstest_geocalclibmain_test.cpp(67) : warning C4250:
'Seq2<double>' : inherits 'Seq1<double>::setValue' via dominance
d:projetstest_geocalclibmain_test.cpp(49) : see declaration of
'setValue'
d:projetstest_geocalclibmain_test.cpp(120) : see reference to
class template instantiation 'Seq2<double>' being compiled
d:projetstest_geocalclibmain_test.cpp(67) : warning C4250:
'Seq2<double>' : inherits 'Seq1<double>::getValue' via dominance
d:projetstest_geocalclibmain_test.cpp(50) : see declaration of
'getValue'
d:projetstest_geocalclibmain_test.cpp(120) : see reference to
class template instantiation 'Seq2<double>' being compiled

Linking...
Main_test.obj : error LNK2001: unresolved external symbol "public: virtual
class ISeq<double> & __thiscall ISeq<double>::operator=(class ISeq<double>
const &)" (??4?$ISeq@N@@UAEAAV0@ABV0@@Z)
Debug/Test_GeoCalcLib.exe : fatal error LNK1120: 1 unresolved externals
Error executing link.exe.

La compilation ne pose donc de problèmes ni à Visual C++ 6.0 ni à gcc 3.3.1
en revanche, tout lesdeux échouent lors de l'édition des liens....

Pour la question d'un autre post du fil sur le destructeur, oui un
destructeur peut être déclaré virtuel pur, et doit avoir une
implémentation si on veux pouvoir instancier des classes dérivées
c'est du moins ce que j'ai compris en regardant la norme.
--
0% de pub! Que du bonheur et des vrais adhérents !
Vous aussi inscrivez-vous sans plus tarder!!
Message posté à partir de http://www.gyptis.org, BBS actif depuis 1995.




Back to top
Christophe de Vienne
Guest





PostPosted: Fri Sep 26, 2003 12:57 pm    Post subject: Re: template operator= et héritage Reply with quote

Mathieu Peyréga wrote:

Quote:
Il me semble que les destructeurs doivent forcément avoir une
implémentation, même si on ajoute '= 0' à la définition.

Ou as-tu implémenté ces fonctions ? L'erreur au link ne serait pas qu'il
manque les fonctions SeqX::SeqX et SeqX::~SeqX ?

A+

Christophe

c'est le cas... il sont implémentés si tu regardes le code fourni
l'erreur se produit au link et est relative à la première instruction
d'affectation du main


oui, j'ai vu mais un peu tard. Je me suis fais avoir parce que certaines
fonctions étaient implémentées directement dans la déclaration de la
classe... J'ai lu un peu vite :-)

A+

Christophe

--
Christophe de Vienne
Experience is something you don't get until just after you need it.
Oliver's Law.

Back to top
Christophe Lephay
Guest





PostPosted: Fri Sep 26, 2003 1:19 pm    Post subject: Re: template operator= et héritage Reply with quote

"DG" <dany42NOSPAM (AT) free (DOT) fr> a écrit dans le message de
news:86isng7z2q.fsf (AT) macphisto (DOT) homeunix.org...
Quote:
kanze (AT) gabi-soft (DOT) fr writes:
Quand tu fais « *pA = *pB », tu affectes un Seq2 à un Seq1. Le
compilateur résoud le surcharge en faveur de l'affectation par copie
(Seq1 étant une base de Seq2), et essaie donc de générer une
implémentation implicitement aussi. Et c'est là que le bat blesse -- la
version générée appelle les opérateurs d'affectation des classes de
base.

Pour ma part, j'ai un peu de mal à comprendre là. Si je t'ai bien suivi,
le compilateur génère implicitement l'implémentation suivante:
ISeq1& operator=( ISeq1 const& );

et c'est cette implémentation qui est utilisée lors du « *pA = *pB »
alors pourquoi a-t-on aussi besoin de d'une implémentation de
l'opérateur d'affectation dans les classes de bases ? Est-ce que c'est
le même mécanisme que lorsqu'une classe B hérite d'une classe A, lors
de l'instanciation d'un objet de type B, la constructeur de A puis
celui de B est appelé ?

*pA = *pB; est équivalent à *pA.operator=( *pB );

L'opérateur d'affectation appelé est donc celui qui se trouve dans la classe
Seq1, dans laquelle on se connait rien de Seq2...

Chris



Back to top
Mathieu Peyréga
Guest





PostPosted: Fri Sep 26, 2003 1:32 pm    Post subject: Re: template operator= et héritage Reply with quote

Quote:
*pA = *pB; est équivalent à *pA.operator=( *pB );

L'opérateur d'affectation appelé est donc celui qui se trouve dans la classe
Seq1, dans laquelle on se connait rien de Seq2...
Chris

Au pire, Seq2 est de type Seq1 et donc l'opérateur

Seq1<T>& operator=(Seq1<T> const& obj);

défini implcitement devrait être apellé non ?

comme de plus l'opérateur ISeq<T>& operator=(ISeq<T> const& obj);
est défini et virtuel, il devrait logiquement être apellé... enfin c'est
ce à quoi je m'attendais
--
0% de pub! Que du bonheur et des vrais adhérents !
Vous aussi inscrivez-vous sans plus tarder!!
Message posté à partir de http://www.gyptis.org, BBS actif depuis 1995.




Back to top
kanze@gabi-soft.fr
Guest





PostPosted: Fri Sep 26, 2003 2:34 pm    Post subject: Re: template operator= et héritage Reply with quote

DG <dany42NOSPAM (AT) free (DOT) fr> wrote

Quote:
kanze (AT) gabi-soft (DOT) fr writes:

[...]

Quand tu fais « *pA = *pB », tu affectes un Seq2 à un Seq1. Le
compilateur résoud le surcharge en faveur de l'affectation par copie
(Seq1 étant une base de Seq2), et essaie donc de générer une
implémentation implicitement aussi. Et c'est là que le bat blesse --
la version générée appelle les opérateurs d'affectation des classes
de base.

Pour ma part, j'ai un peu de mal à comprendre là. Si je t'ai bien
suivi, le compilateur génère implicitement l'implémentation suivante:
ISeq1& operator=( ISeq1 const& );

Si l'utilisateur ne déclare pas un opérateur d'affectation à copie, le
compilateur en génère implicitement une declaration. La signature de la
declaration dépend en partie de la classe (ou plutôt, de ses membres et
de ses bases), mais en général, c'est celle-là.

Si l'opérateur finit par servir, le compilateur génère aussi
l'implémentation. L'implémentation implicite, c'est simplement d'appeler
le même opérateur pour tous les membres et toutes les bases.

Quote:
et c'est cette implémentation qui est utilisée lors du « *pA = *pB »

Dans ce cas-ci, oui. C'est un peu subtile, du fait que pB n'est pas un
Seq1. Mais c'est quand même cet opérateur que le compilateur trouve.

Quote:
alors pourquoi a-t-on aussi besoin de d'une implémentation de
l'opérateur d'affectation dans les classes de bases ?

Parce que c'est ce que la version implicite appelle. Elle effectue une
affectation membre à membre (et base à base).

Quote:
Est-ce que c'est le même mécanisme que lorsqu'une classe B hérite
d'une classe A, lors de l'instanciation d'un objet de type B, la
constructeur de A puis celui de B est appelé ?

Pas tout à fait, mais prèsque. (La différence, c'est que dans le cas
d'un constructeur, le compilateur s'arrange à n'appeler le constructeur
qu'une fois par sous-objet, tandis que dans le cas de l'opérateur
d'affectation, il fait de façon bête -- l'operator= d'une base virtuelle
risque alors d'être appeler plusieurs fois.)

--
James Kanze GABI Software mailto:kanze (AT) gabi-soft (DOT) fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16

Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (French) All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.