FAQ C++/CLI et VC++.NetConsultez toutes les FAQ

Nombre d'auteurs : 29, nombre de questions : 248, création le 22 février 2013 

 
OuvrirSommaireLe langage C++/CLILa surcharge d'opérateur

La surcharge d'opérateur du C++/CLI part du même principe que pour le C++. Elle permet de tirer parti de l'intuition des utilisateurs de la classe. L'utilisateur va en effet pouvoir écrire son code en s'exprimant dans le langage du domaine plutôt que dans celui de la machine.

Cependant, il y a quelques différences. La différence majeure vient de la capacité du framework .Net d'être utilisé à travers plusieurs langages. Ainsi, cet aspect impose que les opérateurs de surcharge en C++/CLI soient déclarés en static.
Remarque : On ne peut pas surcharger l'opérateur gcnew, alors qu'on peut surcharger new en C++ natif. C'est également le cas pour les opérateurs delete, new, [] et ().

Mis à jour le 12 juillet 2006  par nico-pyright(c)

Lien : http://cpp.developpez.com/faq/cpp/?page=surcharge/

Etant donnée que l'on peut utiliser la surcharge d'opérateur en C++ natif, pourquoi utiliser la surcharge du C++/CLI ?

Cette question revient à se poser la question de pourquoi utiliser une classe référence plutôt qu'une classe C++.
Il y a bien sur plusieurs raisons pour un tel choix, citons par exemple la gestion de la classe par le garbage collector ou la possibilité d'utiliser cette classe depuis un autre langage .Net (C#, VB.Net, etc ...).

Si l'on choisit d'implémenter une classe référence, on est obligé d'utiliser la surcharge d'opérateur du C++/CLI. Et comme une classe ref ne supporte pas les fonctions amies (friend), il devient indispensable d'utiliser des fonctions statiques pour les opérateurs binaires.

Créé le 9 mai 2006  par nico-pyright(c)

J'ai écrit une petite classe pour l'occasion qui me permet d'illustrer la surcharge de différents opérateurs. (Cette classe n'est bien sur pas complète et ne gère pas non plus les erreurs).
Il s'agit d'une classe Temps, composée d'un entier heure, d'un entier minute et d'un entier seconde. Vous l'aurez compris, nous allons additionner des Temps.
Pour cet exemple, nous surchargeons l'opérateur unaire + qui additionne deux Temps, puis les opérateurs binaires + qui additionnent un Temps et un entier représentant un nombre de secondes (et inversement). Il s'agira ensuite d'implémenter l'opérateur ++ qui ajoutera simplement une seconde à notre Temps.

 
Sélectionnez

ref class Temps
{
private:
	int heure;
	int min;
	int sec;
public:
	Temps(int h, int m, int s)
	{
		heure = h;
		min = m;
		sec = s;
	}
	virtual String^ ToString() override
	{
		return "Il est " + heure + ":" + min + ":" + sec; 
	}
 
	Temps^ operator+(Temps^ t)
	{
		int s = (sec + t->sec)`;
		int m = (min + t->min + (sec + t->sec)/60)`;
		int h = (heure + t->heure + (min + t->min + (sec + t->sec)/60)/60)$;
		return gcnew Temps(h, m, s);
	}
	static Temps^ operator+(Temps^ t, int sec);
	static Temps^ operator+(int sec, Temps^ t);
	static Temps^ operator++(Temps^ t);
};
 
Temps^ Temps::operator+(Temps ^ t, int sec)
{
	int s = (sec + t->sec)`;
	int m = (t->min + (sec + t->sec)/60)`;
	int h = (t->heure + (t->min + (sec + t->sec)/60)/60)$;
	return gcnew Temps(h, m, s);
}
Temps^ Temps::operator+(int sec, Temps ^ t)
{
	return t+sec;
}
Temps^ Temps::operator++(Temps^ t)
{
	return t+1;
}
 
int main(array<System::String ^> ^args)
{
	Temps ^t1 = gcnew Temps(3,20, 40);
	Temps ^t2 = gcnew Temps(4,50, 20);
	Console::WriteLine(t1+t2);
	Console::WriteLine(t1+10);
	Console::WriteLine(90+t1);
	Console::WriteLine(++t1);
	Console::WriteLine(t1);
}			
			

Remarques

  • Nous sommes obligés d'implémenter une surcharge avec des méthodes statiques pour les opérateurs + avec un entier et l'opérateur ++. (en effet, une classe ref ne supporte pas les classes amies (friend)).
    Notez aussi que l'on définit une seule fois l'opérateur ++ et que nous pouvons écrire t1++ ou ++t1.
  • On implémente la surcharge de la même façon pour une classe référence ou pour une classe de valeur. La seule différence vient du fait que dans un cas, on utilise des handles ^.
Créé le 9 mai 2006  par nico-pyright(c)

Pour implémenter une propriété (un accesseur), on utilise le mot clé property. On peut soit l'avoir en lecture seule uniquement (implémentation de get uniquement), en écriture seule (implémentation de set uniquement) ou en lecture/écriture (implémentation de get et de set).

 
Sélectionnez
ref class Personne
{
private:
	String ^_nom;
	String ^_prenom;
	int ^_age;
public:
	Personne(String ^nom, String ^prenom, int age) : _nom(nom), _prenom(prenom), _age(age) {}
	property String ^Nom
	{
		String ^ get() { return _nom; }
	}
	property String ^Prenom
	{
		String ^ get() { return _prenom; }
		void set(String ^value) { _prenom = value; }
	}
	property int Age
	{
		void set(int value) { _age = value; }
	}
	virtual String ^ ToString() override
	{
		return String::Format("Je m'appelle {0} {1} et j'ai {2} ans", _prenom, _nom, _age);
	}
};
 
int main()
{
	Personne ^ moi = gcnew Personne("Pyright", "", 15);
	moi->Prenom = "Nico";
	moi->Age = 28;
	// int a = moi->Age;  => error C2039: 'get' : is not a member of 'Personne::Age'
	Console::WriteLine(moi->Nom);
	Console::WriteLine(moi);
}

Une manière très simple de simplifier la propriété en lecture et écrire Prenom ci-dessus (qui affecte et retourne un membre privé) est de la remplacer par cette écriture :

 
Sélectionnez
property String ^Prenom;
Mis à jour le 9 octobre 2008  par nico-pyright(c)

Il s'agit de créer une classe qui contient une propriété d'indexation par défaut :

 
Sélectionnez

ref class Jours
{
private:
	array<String^>^ lesJours;
public:
	Jours(...array<String^>^ j) : lesJours(j) {}
 
	property int Length
	{
		int get()
		{
			return lesJours->Length;
		}
	}
	property String^ default[int]
	{
		String^ get(int index)
		{
			if(index >= lesJours->Length)
				throw gcnew Exception("Index en dehors des limites");
			return lesJours[index];
		}
		void set(int index, String^ elt)
		{
			if(index >= lesJours->Length)
				throw gcnew Exception("Index en dehors des limites");
			lesJours[index] = elt;
		}
	}
};
 
int main(array<System::String ^> ^args)
{
	Jours ^ lesjours = gcnew Jours("Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi", "Dimance");
 
	lesjours[3] = "Jeudi c'est permis";
	for(int i = 0 ; i < lesjours->Length; i++)
		Console::WriteLine("Le jour {0} est {1}", i+1, lesjours[i]);
}	
				
Créé le 9 mai 2006  par nico-pyright(c)
  

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2006-2007 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.