Héritage et opérateur d'affectation

Le
Alexis Guillaume
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


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 !
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
David Côme
Le #6149561
On Tue, 22 Apr 2008 10:57:59 +0200, Alexis Guillaume

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.


Falk Tannhäuser
Le #6149551
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

Alexis Guillaume
Le #6323871
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.

Fabien LE LEZ
Le #6323861
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&".)

James Kanze
Le #6327131
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

Jean-Marc Bourguet
Le #6330511
James Kanze
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

Alexis Guillaume
Le #6330501
On Apr 23, 10:23 am, James Kanze
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


Gabriel Dos Reis
Le #6350931
Alexis Guillaume
[...]

| 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
Publicité
Poster une réponse
Anonyme