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++/CLIClasses, Interfaces, héritage et types de donnéesLes types de données

Une classe managée veut simplement dire que l'objet est pris en charge par le CLR. Son allocation (avec gcnew) et sa désallocation (utilisant soit delete explicitement, soit utilisant le garbage collector) sont donc entièrement gérées (managed en anglais) par le CLR. Microsoft a essayé de rayer le mot managé de son vocabulaire pour éviter l'abus de langage (pour parler par exemple de C++/CLI plutôt que de C++ managé).

Cet objet est alloué sur le tas (heap) managé par l'intermédiaire de gcnew et est référencé grâce à un handle.

 
Sélectionnez

String ^ str = gcnew String("Ma chaîne managée est alloué sur le heap managé");			
				

La désallocation est automatique grâce au garbage collector.

Evidement, les objets existants du framework .net (comme le String ci-dessus) sont managés.

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

Lien : Comment allouer un objet managé avec gcnew ?
Lien : Qu'est-ce que le garbage collector ?

Pour déclarer une classe non managée par le CLR, on n'utilise aucun autre mot clé que class.

 
Sélectionnez

	class CMaClasseNonManagee
	{
		CMaClasseNonManagee(void);
		~CMaClasseNonManagee(void);
		bool maFonctionNonManagee();
		CString	maChaineNonManagee;
	};			
				

Cette ancienne déclaration fonctionne toujours de la même façon, et est gérée par le CRT, allouée sur le tas (non managé) avec new.

Une classe non managée par le CLR est dite native.

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

Un type ref est un type CLI qui est alloué sur le heap managé. Il est pris complètement en charge par le garbage collector qui gère sa désallocation quand il n'est plus utile.
Le mot clé ref permet de créer donc des objets managés ou des structures managées (on utilise alors ref class ou bien ref struct).

 
Sélectionnez

ref class CMaClasse
{
	CMaClasse(void);
	~CMyClass(void);
	bool maFonction();	
	String ^ monAttributChaine;
};			
			
Créé le 9 mai 2006  par nico-pyright(c)

Un type de valeur (value type) est un type CLI qui est alloué sur la pile et qui est détruit lorsqu'il sort de sa portée. Il se comporte essentiellement comme un type POD (Plain Old Data : un type POD est un type C++ qui possède un équivalent en C. Il correspond aux types composés à partir des types primitifs).

On ne peut pas hériter d'un type de valeur. Ils n'ont pas non plus de constructeur par défaut, de destructeur, d'opérateur de copie ou d'affectation.
Lorsque l'on conçoit un objet qui fonctionne comme un type natif (un int par exemple), alors cette classe est une candidate parfaite pour un type de valeur.
Pour créer un type de valeur, on utilise alors value class ou bien value struct.

 
Sélectionnez

value class MonTypeDeValeur { 
	String^ uneChaine; 
	String^ uneAutreChaine; 
};			
			


Remarque :

  • Les types de valeurs ont été créés pour permettre une copie rapide et efficace de données, sans utiliser d'indirections de mémoire inutile pour y accéder (pas besoin d'une place mémoire dans le garbage collector et d'une place mémoire pour le handle le référençant). Ainsi, le type de mémoire n'est pas stocké sur le heap managé et permet d'éviter l'encombrement du garbage collector. Ils bénéficient de même des optimisations de registre.
  • Sans les types de valeurs, .Net aurait été beaucoup trop lent face à ses concurrents Java et C++, même pour des petits projets.
    Cependant, il faut noter que lors de la phase d'optimisation du compilateur, celui-ci peut décider lui même si le type de valeur aurait été un meilleur choix qu'un type de référence et choisir ainsi le meilleur emplacement pour ce type, dans la plupart des cas.
  • On utilise l'expression "types managés" ou "objets managés" par abus de langage. Il est plus correct de parler de types CLI.

Il est en général recommandé pour le CLS d'utiliser des structures pour les types de valeurs et des classes pour les types de références.

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

Vous trouverez dans ce tableau une équivalence des types natifs avec les types du framework .Net.

Types natifs C++ Types du framework .Net
bool System::Boolean
signed char System::SByte
unsigned char System::Byte
wchar_t System::Char
double et long double System::Double
float System::Single
int, signed int, long, et signed long System::Int32
unsigned int et unsigned long System::UInt32
__int64 et signed __int64 System::Int64
unsigned __int64 System::UInt64
short et signed short System::Int16
unsigned short System::UInt16
void System::Void
Créé le 12 juillet 2006  par nico-pyright(c)

Les énumérations C++/CLI diffèrent sensiblement des énumérations du C++ ISO/ANSI. Elles correspondent par défaut à des entiers.
Dans la mesure où ces énumérations sont des types CLI, elles doivent être définies en global. Il est impossible d'avoir une définition locale.

 
Sélectionnez

enum class Jours{Lundi, Mardi, Mercredi, Jeudi, Vendredi, Samedi, Dimanche};
 
Jours jeudi = Jours::Jeudi;
				

Il est possible de définir un type différent pour les énumérations, dans la liste suivante :
short, int, long, long long, signed char, char, unsigned short, unsigned int , unsigned long, unsigned long long, unsigned char et bool.
Ainsi, il est possible de définir une énumération de type bool :

 
Sélectionnez

enum class JoursDeLaSemaine : bool {Lundi = true, Mardi = true, Mercredi = true, 
				Jeudi = true, Vendredi = true, Samedi = false, Dimanche = false};
				
Créé le 9 mai 2006  par nico-pyright(c)

On se sert d'un literal en C++/CLI comme on se servirait d'une variable static const en C++.
Cette variable doit être initialisée à sa déclaration et est une manière élégante de nommer des constantes.

 
Sélectionnez

ref struct constMath
{
	literal double pi = 3.14159265;
	literal double nombreOr = 1.61803399;
};
 
int main()
{
	static const int rayon = 5;
	double circonference = 2*rayon*constMath::pi;
	return 0;
}
				
Créé le 12 juillet 2006  par nico-pyright(c)

Une variable initonly fonctionne comme un literal à la différence qu'elle n'est pas obligée d'être initialisée à sa construction.
Cela veut dire qu'on peut par exemple initialiser cette variable dans un constructeur. Par contre, une fois initialisée, il sera impossible de la changer.

 
Sélectionnez

ref class constMath
{
public:
	initonly double pi;
	constMath(int x)
	{
		pi = x;
	}
};
				
Créé le 12 juillet 2006  par nico-pyright(c)

En C/C++, on utilise 0 ou null pour savoir si un pointeur est null.
En C++/CLI, lorsqu'on affecte 0 à un handle, il s'effectue une conversion (un boxing) en Int32 qui sera castée en Object ^.
Ainsi le C++/CLI nous offre un nouveau mot clé : nullptr.

 
Sélectionnez

MonObjet ^m = nullptr;
if (m == nullptr) 
	.... 
				

nullptr correspond aux nothing et null du VB.Net et du C#.

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.