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

operateur + comme fonction virtuelle pure dans une classe de base

33 réponses
Avatar
Marc
Bonjour, mon compilateur me refuse la définition de classe suivante :

class CTypeBase {

public :

CTypeBase() : _ismissing(true) {}
CTypeBase(const CTypeBase &x) : _ismissing(x._ismissing) {}

const bool& is_missing(void) const { return _ismissing;}
void set_missing(void) { _ismissing=true;}

// opérateurs de base redéfinis

virtual const CTypeBase operator+(const CTypeBase&) const=0;

protected :
private :

bool _ismissing;

};

Il m'indique juste que la classe CTypeBase ne peut contenir des fonctions
pures.
Ah bon !? pourquoi ?
ça n'a aucun sens pour moi de définir l'opérateur + dans la classe de base !
Merci de vos lumières

10 réponses

1 2 3 4
Avatar
Jean-Marc Bourguet
"Marc" writes:

Bonjour, mon compilateur me refuse la définition de classe suivante :

class CTypeBase {

public :

CTypeBase() : _ismissing(true) {}
CTypeBase(const CTypeBase &x) : _ismissing(x._ismissing) {}

const bool& is_missing(void) const { return _ismissing;}
void set_missing(void) { _ismissing=true;}

// opérateurs de base redéfinis

virtual const CTypeBase operator+(const CTypeBase&) const=0;
Mon compilateur indique ici:

"marc.cc", line 13: Error: Cannot return a value of abstract class CTypeBase.

protected :
private :

bool _ismissing;

};


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
Marc Boyer
In article <417e532e$0$28190$, Marc wrote:
Bonjour, mon compilateur me refuse la définition de classe suivante :

class CTypeBase {

public :

CTypeBase() : _ismissing(true) {}
CTypeBase(const CTypeBase &x) : _ismissing(x._ismissing) {}

const bool& is_missing(void) const { return _ismissing;}
void set_missing(void) { _ismissing=true;}

// opérateurs de base redéfinis

virtual const CTypeBase operator+(const CTypeBase&) const=0;

protected :
private :

bool _ismissing;

};

Il m'indique juste que la classe CTypeBase ne peut contenir des fonctions
pures.
Ah bon !? pourquoi ?
ça n'a aucun sens pour moi de définir l'opérateur + dans la classe de base !


Si tu utilises l'héritage pour réutiliser une implémentation, du
vas surement utiliser du polymorphisme dynamique, donc

virtual const CTypeBase& operator+(const CTypeBase&) const=0;

Ceci dit, je ne suis pas sur que l'héritage soit ici la solution
la plus pertinente. Pourquoi pas des templates plutôt ?

Marc Boyer
--
Je ne respecte plus le code de la route à vélo depuis une double fracture
due au fait que j'étais le seul à le respecter.

Avatar
Marc
de base redéfinis

virtual const CTypeBase operator+(const CTypeBase&) const=0;
Mon compilateur indique ici:

"marc.cc", line 13: Error: Cannot return a value of abstract class
CTypeBase.


merci, c'est bien ça qui le bloque !


au moins ton compilo est plus explicite dans ses messages d'erreur...
Mais ça m'embête, car il s'agit justement d'une fonction virtuelle pure et
bien sûr je ne retournerai que des objets dérivés de CTypeBase.
Alors comment faire ?
Marc


Avatar
Marc
virtual const CTypeBase& operator+(const CTypeBase&) const=0;
Je comprends ce que tu cherches à faire,

mais à mon avis, il vaut mieux retourner l'objet par valeur !
Tu retournes une référence sur quoi ?

Je cherche à implémenter le modèle "double-dispatch", comme ci-après

class CTypeInt;
class CTypeBase {

public :

CTypeBase() : _ismissing(true) {}
CTypeBase(const CTypeBase &x) : _ismissing(x._ismissing) {}

const bool& is_missing(void) const { return _ismissing;}
void set_missing(void) { _ismissing=true;}

// opérateurs de base redéfinis

virtual const CTypeInt operator+(const CTypeBase&) const=0;
virtual const CTypeBase operator+(const CTypeInt&) const =0;
protected :
private :

bool _ismissing;

};

class CTypeInt : public CTypeBase {

public :

CTypeInt() : CTypeBase() {}
CTypeInt(const CTypeInt &x) : CTypeBase(x),_value(x._value) {}

virtual const CTypeBase operator+(const CTypeBase&) const {return
x.operator +(*this);}
virtual const CTypeBase operator+(const CTypeInt&) const {...}

private :

int _value;

};

Avatar
Marc
virtual const CTypeBase& operator+(const CTypeBase&) const=0;
Je comprends ce que tu cherches à faire,

mais à mon avis, il vaut mieux retourner l'objet par valeur !
Tu retournes une référence sur quoi ?

Je cherche à implémenter le modèle "double-dispatch", comme ci-après

class CTypeInt;
class CTypeBase {

public :

CTypeBase() : _ismissing(true) {}
CTypeBase(const CTypeBase &x) : _ismissing(x._ismissing) {}

const bool& is_missing(void) const { return _ismissing;}
void set_missing(void) { _ismissing=true;}

// opérateurs de base redéfinis

virtual const CTypeBase operator+(const CTypeBase&) const=0; //
<---- corrigé ici
virtual const CTypeBase operator+(const CTypeInt&) const =0;
protected :
private :

bool _ismissing;

};

class CTypeInt : public CTypeBase {

public :

CTypeInt() : CTypeBase() {}
CTypeInt(const CTypeInt &x) : CTypeBase(x),_value(x._value) {}

virtual const CTypeBase operator+(const CTypeBase&) const {return
x.operator +(*this);}
virtual const CTypeBase operator+(const CTypeInt&) const {...}

private :

int _value;

};

Avatar
Arnaud Meurgues
Marc wrote:

Mais ça m'embête, car il s'agit justement d'une fonction virtuelle pure et
bien sûr je ne retournerai que des objets dérivés de CTypeBase.
Alors comment faire ?


Si tu retournes des objets dérivés de CTypeBase, alors tu ne peux les
retourner par valeur. Comme c'est écrit ici, ça veut dire que tu
retournes une instance de CTypeBase, ce qui n'est pas possible puisque
CTypeBase est une classe abstraite.

Il faut obligatoirement retourner une référence ou un pointeur (ici,
plutôt une référence).

--
Arnaud
(Supprimez les geneurs pour me répondre)

Avatar
Marc Boyer
In article <417e5c6a$0$24427$, Marc wrote:
virtual const CTypeBase& operator+(const CTypeBase&) const=0;
Je comprends ce que tu cherches à faire,

mais à mon avis, il vaut mieux retourner l'objet par valeur !
Tu retournes une référence sur quoi ?


J'ai été trop rapide, oui. Le code compile, mais de là
à lui donner une sémantique...

Je cherche à implémenter le modèle "double-dispatch", comme ci-après


Désolé de ne pas pouvoir plus aider.

Marc Boyer
--
Je ne respecte plus le code de la route à vélo depuis une double fracture
due au fait que j'étais le seul à le respecter.


Avatar
Arnaud Meurgues
Marc wrote:
virtual const CTypeBase& operator+(const CTypeBase&) const=0;


Je comprends ce que tu cherches à faire,
mais à mon avis, il vaut mieux retourner l'objet par valeur !


Ben oui, mais non. Le polymorphisme ne marche qu'à travers des
références ou des pointeurs. Si l'on écrit
CTypeBase
ça veut dire que le type de l'objet est obligatoirement CTypeBase, et
non pas une classe dérivée ou une superclasse.

--
Arnaud
(Supprimez les geneurs pour me répondre)


Avatar
Jean-Marc Bourguet
"Marc" writes:

virtual const CTypeBase& operator+(const CTypeBase&) const=0;
Je comprends ce que tu cherches à faire,

mais à mon avis, il vaut mieux retourner l'objet par valeur !


Cherche apres l'idiome lettre/enveloppe.

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
Marc
Ben oui, mais non. Le polymorphisme ne marche qu'à travers des
références ou des pointeurs. Si l'on écrit
CTypeBase
ça veut dire que le type de l'objet est obligatoirement CTypeBase, et
non pas une classe dérivée ou une superclasse.
pourquoi ?

je peux tout à fait écrire
virtual const ClasseDeBase operator+(const ClasseDeBase &) const { return
ClasseDerivee();}
Ce qui m'intéresse, c'est que ce soit le bon operator+ qui soit sélectionné.

Pour mon problème, j'ai trouvé une solution toute bête, dont voici le code
simplifié :

class CTypeInt;
class CTypeBase {

friend class CTypeInt;
public :

CTypeBase() : _ismissing(true) {}
CTypeBase(const CTypeBase &x) : _ismissing(x._ismissing) {}

const bool& is_missing(void) const { return _ismissing;}
void set_missing(void) { _ismissing=true;}

// opérateurs de base redéfinis

virtual const CTypeBase operator+(const CTypeBase&) const { return
CTypeBase();}

protected :

virtual const CTypeBase operator+(const CTypeInt&) const { return
CTypeBase();}

bool _ismissing;

};


class CTypeInt : public CTypeBase {

public :

CTypeInt() : CTypeBase() {}
CTypeInt(const CTypeInt &x) : CTypeBase(x),_value(x._value) {}

virtual const CTypeBase operator+(const CTypeBase&) const;

protected :

virtual const CTypeBase operator+(const CTypeInt&) const;

int _value;

};

En fait, je définis les opérateurs dans la classe de base, qui n'est plus
abstraite, même si je ne m'en servirai jamais. J'ai trouvé sur Google une
solution "esthétique" qui permet de conserver la classe de base abstraite
(avec des proxy), mais c'est une usine à gaz qui rend le code
incompréhensible et à mon avis peu performant...

Pour info, l'implémentation de operator+ dans la classe dérivée serait un
truc du genre :

const CTypeBase CTypeInt::operator +(const CTypeBase &x) const
// implémentation : CTypeInt+CTypeBase retourne CTypeInt
{
if (_ismissing || x._ismissing)
return CTypeInt();
else
return x.operator +(*this);
}

const CTypeBase CTypeInt::operator +(const CTypeInt &x) const
{
CTypeInt entier;
if (_ismissing || x._ismissing)
return entier;
entier._ismissingúlse;
entier._value=_value+x._value;
return entier;
}

J'espère que je reste compréhensible...
Merci à vous

1 2 3 4