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

Héritage et opérateur d'affectation

8 réponses
Avatar
Alexis Guillaume
Bonjour =E0 tous !
Le code suivant ne compile pas :
-----
#include <string>

class A {
public:
A const & operator =3D (std::string const &str) {}
A const & operator +=3D ( std::string const &str ) {}
};
class B : public A {
};
int main() {
B b;
b +=3D "titi"; // Ok
b =3D "titi"; // Erreur
}
-----
heritage.cc: In function =91int main()=92:
heritage.cc:14: error: no match for =91operator=3D=92 in =91b =3D "titi"=92
heritage.cc:8: note: candidates are: B& B::operator=3D(const B&)
-----
Ce que je ne comprends pas c'est que l'op=E9rateur +=3D (utilis=E9 ici pour
l'exemple) fonctionne bien, mais pas l'affectation. Cela signifie donc
que l'op=E9rateur =3D est trait=E9 diff=E9rement des autres ?

Bon, en supposant qu'il ne soit vraiment pas possible d'avoir un
op=E9rateur =3D dans une classe de base et de s'en servir dans les classes
d=E9riv=E9es, que puis-je utiliser d'autre ? Mes classes d=E9riv=E9es ne
contiendront jamais aucune variable membre suppl=E9mentaire, mais juste
des fonctions membres pour acc=E9der diff=E9remment aux donn=E9es. C'est
pourquoi j'aimerais bien pouvoir utiliser l'affectation, sans
red=E9finir l'op=E9rateur =E0 chaque fois...


Alexis Guillaume
PS : ceci =E9tant mon premier post par l'interm=E9diaire de google groups,
je croise les doigts pour tout fonctionne correctement (accents,
lignes coup=E9es, etc) ; si ce n'est pas le cas merci de me le
signaler !

8 réponses

Avatar
David Côme
On Tue, 22 Apr 2008 10:57:59 +0200, Alexis Guillaume
wrote:

Bonjour à tous !
Le code suivant ne compile pas :
-----
#include <string>

class A {
public:
A const & operator = (std::string const &str) {}
A const & operator += ( std::string const &str ) {}
};
class B : public A {
};
int main() {
B b;
b += "titi"; // Ok
b = "titi"; // Erreur
}
-----
heritage.cc: In function ‘int main()’:
heritage.cc:14: error: no match for ‘operator=’ in ‘b = "titi"’
heritage.cc:8: note: candidates are: B& B::operator=(const B&)
-----
Ce que je ne comprends pas c'est que l'opérateur += (utilisé ici pour
l'exemple) fonctionne bien, mais pas l'affectation. Cela signifie donc
que l'opérateur = est traité différement des autres ?

Bon, en supposant qu'il ne soit vraiment pas possible d'avoir un
opérateur = dans une classe de base et de s'en servir dans les classes
dérivées, que puis-je utiliser d'autre ? Mes classes dérivées ne
contiendront jamais aucune variable membre supplémentaire, mais juste
des fonctions membres pour accéder différemment aux données. C'est
pourquoi j'aimerais bien pouvoir utiliser l'affectation, sans
redéfinir l'opérateur à chaque fois...


Si je ne me trompe pas, l'opérateur = n'est pas hérité de la classe mère.


Alexis Guillaume
PS : ceci étant mon premier post par l'intermédiaire de google groups,
je croise les doigts pour tout fonctionne correctement (accents,
lignes coupées, etc) ; si ce n'est pas le cas merci de me le
signaler !

Tout marche très bien.


Avatar
Falk Tannhäuser
Alexis Guillaume wrote:
Bonjour à tous !
Le code suivant ne compile pas :
-----
#include <string>

class A {
public:
A const & operator = (std::string const &str) {}
A const & operator += ( std::string const &str ) {}
};
class B : public A {
};
int main() {
B b;
b += "titi"; // Ok
b = "titi"; // Erreur
}
-----
heritage.cc: In function ‘int main()’:
heritage.cc:14: error: no match for ‘operator=’ in ‘b = "titi"’
heritage.cc:8: note: candidates are: B& B::operator=(const B&)


C'est normal - l'opérateur = n'est pas hérité.

Bon, en supposant qu'il ne soit vraiment pas possible d'avoir un
opérateur = dans une classe de base et de s'en servir dans les classes
dérivées, que puis-je utiliser d'autre ? Mes classes dérivées ne
contiendront jamais aucune variable membre supplémentaire, mais juste
des fonctions membres pour accéder différemment aux données. C'est
pourquoi j'aimerais bien pouvoir utiliser l'affectation, sans
redéfinir l'opérateur à chaque fois...


Il n'y a pas le choix, il faut redéfinir l'affectation dans la classe
dérivée, mais heureusement on peut faire appel à l'affectation de la
classe de base pour cela. S'il existe plusieurs opérateurs d'affectation
pour des types différents, un template fait l'affaire :

class B : public A
{
public:
template<typename T> B& operator=(T const& t)
{
A::operator=(t);
return *this;
}
};

Falk

Avatar
Alexis Guillaume
On Apr 22, 11:26 am, Falk Tannhäuser
wrote:
Il n'y a pas le choix, il faut redéfinir l'affectation dans la classe
dérivée, mais heureusement on peut faire appel à l'affectation de la
classe de base pour cela. S'il existe plusieurs opérateurs d'affectation
pour des types différents, un template fait l'affaire :

class B : public A
{
public:
   template<typename T> B& operator=(T const& t)
   {
     A::operator=(t);
     return *this;
   }

};


Cette solution me semble acceptable ; certes il va falloir réécrire ce
code dans chaque classe fille, mais au moins le compilateur protestera
de manière claire si on l'oublie... Je préfère cela à l'utilisation
d'un opérateur différent (obfuscation !) et c'est quand même plus beau
qu'un appel de fonction.

Problème résolu donc... Par contre pour la théorie je ne comprends pas
trop le pourquoi du comment... Je vois bien pourquoi on n'hérite pas
de l'opérateur d'affectation quand celui ci est de la forme :
B const & operator = (B const &);
J'imagine que cela résulterait dans beaucoup de cas en une affectation
partielle (seule les données de la classe de base seront copiées).
Même si je trouve cela inhabituel en C++ de voir une règle pour pour
protéger le programmeur de ses propres bêtises ;-)
Mais en ce qui me concerne, mon opérateur d'affectation prend une
std::string, et il n'éxiste même pas de conversion implicite vers ma
classe depuis une std::string, alors pourquoi ne pas en permettre
l'héritage ?

Alexis Guillaume.

Avatar
Fabien LE LEZ
On Wed, 23 Apr 2008 00:07:55 -0700 (PDT), Alexis Guillaume
:

Par contre pour la théorie je ne comprends pas
trop le pourquoi du comment...


Imagine le cas suivant :

struct A
{
void f (std::string const&);
};

struct B: A
{
void f (B const&);
};

int main()
{
B b;
b.f ("Hello"); // erreur !
}

Étant donné qu'une fonction B::f() existe, la fonction A::f() n'est
pas héritée par B, même si les arguments ne coïncident pas.

Remplace f par operator= et tu retombes sur le cas qui t'occupe. En
effet, B a forcément un "operator=(B const&)", éventuellement
implicite.

Par ailleurs, note que A::operator= et B::operator= ne renvoient pas
la même chose : un A& et un B&, respectivement.
(Note aussi qu'il y a une erreur dans ton code d'origine :
A::operator= renvoie un A&, pas un "A const&".)

Avatar
James Kanze
On Apr 22, 10:57 am, Alexis Guillaume
wrote:

Le code suivant ne compile pas :
-----
#include <string>

class A {
public:
A const & operator = (std::string const &str) {}
A const & operator += ( std::string const &str ) {}};

class B : public A {};

int main() {
B b;
b += "titi"; // Ok
b = "titi"; // Erreur
}

-----
heritage.cc: In function ?int main()?:
heritage.cc:14: error: no match for ?operator=? in ?b = "titi"?
heritage.cc:8: note: candidates are: B& B::operator=(const B&)
-----
Ce que je ne comprends pas c'est que l'opérateur += (utilisé
ici pour l'exemple) fonctionne bien, mais pas l'affectation.
Cela signifie donc que l'opérateur = est traité différement
des autres ?


Un peu. En fait, à cet égard, il se comporte exactement comme
n'importe quelle autre fonction. Seulement, si toi, tu ne
déclare pas de operator= de copie dans une classe, le
compilateur en déclare un pour toi. Un qui cache la déclaration
dans la classe de base. C'est exactement comme si la fonction
s'appeler « f », et que tu avais déclaré un
« f( B const& ) » dans ta classe B.

La solution en est la même aussi: ajouter un
« using A::operator= ; » dans la class B.

Alexis Guillaume
PS : ceci étant mon premier post par l'intermédiaire de google
groups, je croise les doigts pour tout fonctionne correctement
(accents, lignes coupées, etc) ; si ce n'est pas le cas merci
de me le signaler !


Pas de problème, mais si tu utilise Firefox comme butineur, je
te suggère l'add-on « it's all text », pour pouvoir éditer les
messages avec ton éditeur préféré.

--
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
Jean-Marc Bourguet
James Kanze writes:

Pas de problème, mais si tu utilise Firefox comme butineur, je
te suggère l'add-on « it's all text », pour pouvoir éditer les
messages avec ton éditeur préféré.


Genial. Merci.

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

Avatar
Alexis Guillaume
On Apr 23, 10:23 am, James Kanze wrote:
Un peu. En fait, à cet égard, il se comporte exactement comme
n'importe quelle autre fonction. Seulement, si toi, tu ne
déclare pas de operator= de copie dans une classe, le
compilateur en déclare un pour toi. Un qui cache la déclaration
dans la classe de base. C'est exactement comme si la fonction
s'appeler « f », et que tu avais déclaré un
« f( B const& ) » dans ta classe B.

La solution en est la même aussi: ajouter un
« using A::operator= ; » dans la class B.


Merci à tous pour l'explication et la solution. Je constate que l'on
peut toujours autant compter sur les habitués de ce forum en cas de
souci !

Alexis Guillaume
PS : ceci étant mon premier post par l'intermédiaire de google
groups, je croise les doigts pour tout fonctionne correctement
(accents, lignes coupées, etc) ; si ce n'est pas le cas merci
de me le signaler !


Pas de problème, mais si tu utilise Firefox comme butineur, je
te suggère l'add-on « it's all text », pour pouvoir éditer les
messages avec ton éditeur préféré.


Merci beaucoup. Je suis en effet bien plus heureux en utilisant [Nom
de
l'éditeur censuré pour ne pas lancer une flame-war !]. :-)

--
Alexis Guillaume


Avatar
Gabriel Dos Reis
Alexis Guillaume writes:

[...]

| Merci beaucoup. Je suis en effet bien plus heureux en utilisant [Nom
| de
| l'éditeur censuré pour ne pas lancer une flame-war !]. :-)

Oh :-(

-- Gaby