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++/CLICompatibilité d'assignation et comparaison de d'identité de types

L'opérateur as du C# n'existe pas en C++/CLI. Il est utilisé pour effectuer des conversions entre des types compatibles.
Il retourne nullptr lorsque la conversion est impossible.

En C++, nous allons donc utiliser l'opérateur dynamic_cast pour effectuer une telle tâche.
Ainsi, il suffira d'utiliser le code suivant pour simuler le as du C# (ici T est un type quelconque).

 
Sélectionnez

T t = dynamic_cast<T>(e); // cette ligne uniquement correspond au 'as'
if (t != nullptr)
{
    // ...
} 				
				

On peut rendre ceci générique en utilisant les templates du C++. Il est impossible ici d'utiliser les générics du C++/CLI, car on ne peut pas combiner l'utilisation de dynamic_cast avec ceux-ci.
Voici ce que serait l'implémentation du 'as' C# :

 
Sélectionnez

template < class T, class U > 
T as(U u) 
{
   return dynamic_cast< T >(u);
}				
				

Observons maintenant l'exemple suivant pour illuster cette fonction :

 
Sélectionnez

ref class class1 {};
ref class class2 {};
 
int main() 
{
	array<Object ^> ^tabObj = gcnew array<Object ^>(6);
	tabObj[0] = gcnew class1();
	tabObj[1] = gcnew class2();
	tabObj[2] = "chaine";
	tabObj[3] = 123;
	tabObj[4] = 123.4;
	tabObj[5] = nullptr;
 
	for (int i = 0; i < tabObj->Length ; i++)
	{
		String ^ s = as<String ^>(tabObj[i]);
		Console::Write("{0} : ", i);
		if (s)
			Console::WriteLine("'{0}'", s);
		else
			Console::WriteLine("n'est pas un String ^");
	}
 
	return 0;	
}			
				

Cet exemple produit :

 
Sélectionnez

0 : n'est pas un String ^
1 : n'est pas un String ^
2 : 'chaine'
3 : n'est pas un String ^
4 : n'est pas un String ^
5 : n'est pas un String ^				
				
Créé le 12 juillet 2006  par nico-pyright(c)

L'opérateur is du C# n'existe pas en C++/CLI. Il permet de vérifier si un objet est compatible avec un type. Il effectue cette vérification en runtime.
L'opérateur C++ dynamic_cast est le candidat parfait pour cette vérification.

Il suffit, sur le même principe que Comment implémenter l'opérateur d'assignation 'as' du C# ?, d'utiliser ce code (T étant un type quelconque) :

 
Sélectionnez

T t = dynamic_cast<T>(e);
if (t != nullptr)
{
    // ...
} 				
				

Le 'is' consiste en la combinaison des deux instructions ci-dessus.
On peut en faire une version générique, en utilisant les templates du C++. (En effet, on ne peut pas utiliser les générics du C++/CLI à cause de dynamic_cast).

 
Sélectionnez

template < class T, class U > 
Boolean is(U u) 
{
   return dynamic_cast< T >(u) != nullptr;
}				
				

Observons maintenant l'exemple suivant pour illuster cette fonction :

 
Sélectionnez

void Test(Object ^o)
{
	if (is<String ^>(o))
	{
		Console::WriteLine("o est une chaine");
		String ^a = safe_cast<String ^>(o);
		DoSomethingWith(a);
	}
	else if (is<Boolean ^>(o))
	{
		Console::WriteLine("o est un Boolean");
		Boolean ^ b = safe_cast<Boolean ^>(o);
		DoSomethingWith(b);
	}
	else
		Console::WriteLine("o n'est ni une chaine , ni un Boolean");
}
 
int main() 
{
	String ^s = gcnew String("chaine");
	Boolean ^a = gcnew Boolean(true);
	Test(s);
	Test(a);
	Test(1234);
 
	return 0;	
}			
				

On obtient en sortie :

 
Sélectionnez

o est une chaine
o est un Boolean
o n'est ni une chaine , ni un Boolean				
				
Créé le 12 juillet 2006  par nico-pyright(c)

Nous avons vu dans Comment implémenter l'opérateur d'assignation 'as' du C# ? et dans Comment implémenter l'opérateur 'is' du C# ? comment effectuer une comparaison d'assignation.
Il peut être utile dans certains cas d'effectuer une comparaison d'identité.

Ces deux concepts sont différents dans la mesure où dans la comparaison d'assignation, on va vérifier si les types sont compatibles entre eux alors que dans la comparaison d'identité, on va vérifier si les types sont de même type.
On utilise pour ca la capacité du framework .Net de reflexion (d'introspection), en comparant le type d'un objet (méthode GetType) et le type d'un Type (méthode statique typeid).

Créons donc une fonction générique en C++/CLI pour cette comparaison :

 
Sélectionnez

generic <typename T, typename U>
bool isIdentity(U u)
{
	return T::typeid == u->GetType();
}				
				

Nous allons illustrer cette fonction à travers l'exemple suivant, qui consiste à remettre à zéro tous les contrôles de type "textbox" dans une Winform, en parcourant tous les contrôles et en testant l'identité de ceux-ci :

 
Sélectionnez

for each (Control ^c in this->Controls)
	if (isIdentity<TextBox ^>(c))
		c->Text = "";				
				
Créé le 12 juillet 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.