Forum Clubic

Surchage de l'opérateur == dans une methode virtuelle en utilisant un template en argument (C++)

Bonjour,

Je cherche à surcharger l’operateur d’égalité pour pouvoir comparer deux objets.
Je posséde une structure (sLayer) une classe mère (Geometry) et deux classes filles (Rectangle,Circle).



struct sLayer
	{
	std::string name;
	std::vector<Geometry*> tab_geom;
	};

template <class T>
class Geometry//Geometry mathematique (2D)
	{
	private :
		
	
	public :
		string name;
		Geometry();
		~Geometry();
		virtual bool operator == (T&);
		virtual void print_info();
	
	};

template <class T>
class Circle : public Geometry<>
	{
	private :
		
	
	public :
		Coordinate center;
		float diameter;
		float width;
		bool fill;//0=vide 1=plein
		Circle(Coordinate coo_tmp,float diameter_tmp,float width_tmp) : center(coo_tmp),diameter(diameter_tmp),width(width_tmp),fill(0){}
		Circle();
		~Circle();
		virtual bool operator == (T);
		virtual void print_info();
		virtual void get_info();
	
	};

template <class T>
class Rectangle : public Geometry
	{
	private :
		
	
	public :
		Rectangle(std::string,std::string,float);
		Rectangle(std::string,std::string);
		Rectangle();
		~Rectangle();
		virtual bool operator == (T);
		virtual void print_info();
	
	};

Le problème c’est que dans ma structure je veux comparer les “Geometry” entre elle et ma syntaxe n’est pas bonne, je ne sais pas comment m’y prendre.

Merci d’avance

C’est quoi l’intérêt des templates dans ton cas ???

Je veux bien que tu ai :

template <class T> Equals {
  virtual bool operator == (const T& other) = 0 const;
}

Qui, si le compilateur est sympa, te laissera définir une méthode virtuelle pure == prenant en paramètre un T constant (et étant constante, tant qu’à faire), et que tu pourras hériter ainsi :

class Circle : Geometry, Equals<Circle> {
  virtual bool operator == (const Circle& other) const {
    return ... ; 
  }
}

Mais je ne suis pas sûr que cela fonctionne, ni même que cela ait du sens d’avoir un opérateur == qui prenne n’importe quoi d’autres qu’un objet de même type sauf à utiliser des pointeurs void* et des trucs plus poussés (voir ci-dessous); l’intérêt résultant peut-être seulement en une interface commune…

virtual bool Circle::operator == (const void* ptr) const {
	if (typeid(ptr) == typeid(this)) {
		return ...;
	}
	return true;
}

Ben en fait comme je veux pouvoir surdefinir == dans ma classe “Geometry” donc pas de virtuel pure, et je veux pouvoir comparer deux “Geometry”, deux “Circle” ou deux “Rectangle” entre eux. Et aussi je veux pouvoir comparer un “Circle” et un “Rectangle” entre eux.

Tu n’as aucun intérêt à utiliser des templates dans ton cas.
Tu peux définir ta méthode d’opérateur == dans ta classe Geometry, et la redéfinir comme tu veux dans tes classes Circle et Rectangle sans aucune difficulté.
Là, tu te perds un peu tout seul en faisant appel à test template.
Dans tous les cas, à droite du paramètre tu auras un objet et tu fais ta validation (et le mieux une descendante)

Bon j’ai tester en utilisant void* en argument plutot que d’utiliser un template, mais je n’arrive pas a avoir accès au variables tel que “width” à partir de l’argument.
Dans n’importe quelle comparaison je veux pouvoir appeler tout type d’objet “Geometry” ou autre dérivant de cette classe. Mettre en argument un objet du type “Geometrie” suffit largement pour concerver le polymorphisme des classes ?

Tu vérifies le type puis tu utilises des casts

allbundy: comme le dit Akkai, passe par une simple définition de méthode. Et de plus, quel est le sens de comparer un Cercle et un Rectangle ? Personnellement, j’en trouve aucun.

Donc selon vous je devrais créer une methode appartenant à la classe “Geometrie” pour faire mes comparaisons, et mettre en argument un objet “Geometrie” en argument de cette methode.

Moi je veux utiliser le == pour comparer.

En fait je ne cherche pas à savoir s’il est logique de comparer un cercle et un rectangle, je veux juste de l’aide pour me remettre dans le C++, ça fait plus de 10 ans que j’en ai pas fait. Mais si vous trouver ma demande extravagante, c’est pas grave, je me débrouillerais tout seul.

Déjà, vu que tu change la classe sur laquelle tu compares, tu n’as pas besoin de méthode virtuelle tout court : une classe héritant de Geometry va avoir sa propre méthode Cercle. Donc chacun a se propre méthode ==.

Pour le reste, utilise pastebin et fait voir ton code tel qu’il est et tel qu’il compile :slight_smile:

Je suis d’accord avec toi.

En fait je veux passer en paramètre de la fonction “==”, un objet ou un pointeur sur un objet du type “Geometry” (classe mère), celui-ci me permettant d’avoir accès aux variables qui sont défini dans les classes filles, sans avoir à les redéfinir dans la classe mère. Car si on fait :



Geometry *obj_geom1=new Geometry();
Geometry *obj_geom2=new Geometry();
Geometry *obj_geom3=new Geometry();

obj_geom_tmp1=new Circle("0 0",2,0.1);
obj_geom_tmp2=new Rectangle("-1 -1","1 1");


if(obj_geom1==obj_geom2)
  {
  }

if(obj_geom2==obj_geom3)
  {
  }

if(obj_geom3==obj_geom1)
  {
  }


Donc j’aimerais savoir comment je dois écrire les surcharges de l’opérateur == pour pouvoir utiliser la syntaxe si dessus.
Et avoir accès à la variable “width” declarée dans la classe “Circle” (définie dans le premier message).


bool Circle::operator == (??????)
   {
   if(typeid(???) == typeid(this))//Si c'est bien deux cercles qu'on compare
      {
      if(0==?????width)
         {}
      }
   else
      {}
   }

Et je sèche à ce niveau car je ne sais pas quoi mettre, le compilateur me jette avec tous les trucs que j’ai essayé.
Edité le 13/06/2011 à 15:21

Essaye ça :

bool Circle::operator == (const void const* other) const {
	if (typeid(*this) == typeid(*other)) {
		const Circle const* circle = static_cast<const Circle const*>(other);
		...
	}
	return false;
}

Maintenant, je pense que tu ne devrais pas faire comme ça puisque cela te donnera de mauvaises pratiques (ie: déduire un type de manière dynamique) qui ne sont pas forcément les mêmes qu’en Java.

Tu devrais te limiter à la simple surcharge d’opérateur et passer en paramètre un const Circle&.

ça ne passe pas, Si j’utilise ta syntaxe, j’ai comme erreur : duplicate `const’ pour la ligne : bool Circle::operator == (const void const* other) const {

Si j’enlève un “const” j’ai comme erreur : `const void*’ is not a pointer-to-object type pour la ligne : if (typeid(*this) == typeid(*other))

Si je fais ça, on ne pourra pas écrire : if(obj_circle==obj_geometry) ou if(obj_circle==obj_rect)

Là encore, on ne compare que des choses comparables. Comparer un Cercle et un Rectangle devrait toujours retourner false. Ou alors, dans ton modèle, c’est qu’ils ont des attributs communs portés par la classe Geometry, et c’est donc que tu as une surcharge d’opérateur == avec const Geometry& en paramètre.

Pour l’erreur const void*, j’ai du mettre des pointeurs en trop (je ne compile pas, pas de compilateur sous la main), essaye typeid(other).

Merci pour les informations, ça m’a beaucoup aidé. Maitenant je reprend un peu du poil de la bête en C++.

Bonne continuation à tous.:hello: