Condividi tramite


Conversioni definite dall'utente (C++/CLI)

In questa sezione vengono illustrate le conversioni definite dall'utente (UDC) quando uno dei tipi nella conversione è un riferimento o un'istanza di un tipo di valore o un tipo di riferimento.

Conversioni implicite e esplicite

Una conversione definita dall'utente può essere implicita o esplicita.Una CDU deve essere implicita se la conversione non comporta una perdita di informazioni.Altrimenti una CDU esplicita deve essere definita.

Il costruttore nativo di una classe può essere utilizzato per convertire un riferimento o un tipo valore a una classe nativa.

Per ulteriori informazioni sulle conversioni, vedere Boxing (Estensioni del componente C++) e Conversioni standard.

// mcpp_User_Defined_Conversions.cpp
// compile with: /clr
#include "stdio.h"
ref class R;
class N;

value class V {
   static operator V(R^) {
      return V();
   }
};

ref class R {
public:
   static operator N(R^);
   static operator V(R^) {
      System::Console::WriteLine("in R::operator N");
      return V();
   }
};

class N {
public:
   N(R^) {
      printf("in N::N\n");
   }
};

R::operator N(R^) {
   System::Console::WriteLine("in R::operator N");
   return N(nullptr);
}

int main() {
   // Direct initialization:
   R ^r2;
   N n2(r2);   // direct initialization, calls constructor
   static_cast<N>(r2);   // also direct initialization

   R ^r3;
   // ambiguous V::operator V(R^) and R::operator V(R^)
   // static_cast<V>(r3);   
}

Output

  

Convertito- Da operatori

Convertito- gli operatori creare un oggetto della classe in cui l'operatore è definito da un oggetto di un'altra classe.

Lo standard C++ non supporta convertito- da operatori, lo standard C++ utilizza i costruttori per questo scopo.Quando tuttavia si utilizzano tipi CLR, Visual C++ fornisce il supporto sintattico a chiamare convertito- gli operatori.

Per interoperare bene con altri linguaggi conformi a CLS, è possibile eseguire il wrapping di ogni costruttore unario definito per una determinata classe con una corrispondenza convertito- dall'operatore.

Convertito- gli operatori:

  • Sarà definito come funzioni statiche.

  • Può essere implicito (per le conversioni non perdono la precisione come breve int) o esplicito, si potrebbe contenere una perdita di precisione.

  • Restituisce un oggetto della classe contenitore.

  • Sarà "da" tipo come tipo di parametro solo.

L'esempio seguente mostra un implicito e esplicito "convertito- da", operatore definito dall'utente di (UDC) di conversione.

// clr_udc_convert_from.cpp
// compile with: /clr
value struct MyDouble {
   double d;

   MyDouble(int i) {
      d = static_cast<double>(i);
      System::Console::WriteLine("in constructor");
   }

   // Wrap the constructor with a convert-from operator.
   // implicit UDC because conversion cannot lose precision
   static operator MyDouble (int i) {
      System::Console::WriteLine("in operator");
      // call the constructor
      MyDouble d(i);
      return d;
   }

   // an explicit user-defined conversion operator
   static explicit operator signed short int (MyDouble) {
      return 1;
   }
};

int main() {
   int i = 10;
   MyDouble md = i;
   System::Console::WriteLine(md.d);
 
   // using explicit user-defined conversion operator requires a cast  
   unsigned short int j = static_cast<unsigned short int>(md);
   System::Console::WriteLine(j);
}

Output

  

Convertito- operatori

Convertito- agli operatori di conversione di un oggetto della classe in cui l'operatore è definito in un altro oggetto.L'esempio seguente mostra un implicito, convertito- a, l'operatore di conversione definito da l:

// clr_udc_convert_to.cpp
// compile with: /clr
using namespace System;
value struct MyInt {
   Int32 i;

   // convert MyInt to String^
   static operator String^ ( MyInt val ) {
      return val.i.ToString();
   }

   MyInt(int _i) : i(_i) {}
};

int main() {
   MyInt mi(10);
   String ^s = mi;
   Console::WriteLine(s);
}

Output

  

Un definito esplicito convertito- l'operatore di conversione è appropriato per le conversioni che potenzialmente perdono i dati in qualche modo.Per richiamare un esplicito convertito- all'operatore, un cast deve essere utilizzato.

// clr_udc_convert_to_2.cpp
// compile with: /clr
value struct MyDouble {
   double d;
   // convert MyDouble to Int32
   static explicit operator System::Int32 ( MyDouble val ) {
      return (int)val.d;
   }
};

int main() {
   MyDouble d;
   d.d = 10.3;
   System::Console::WriteLine(d.d);
   int i = 0;
   i = static_cast<int>(d);
   System::Console::WriteLine(i);
}

Output

  

Per convertire le classi generiche

È possibile convertire una classe generica a T.

// clr_udc_generics.cpp
// compile with: /clr
generic<class T> 
public value struct V {
   T mem;
   static operator T(V v) {
      return v.mem;
   }
   
   void f(T t) {
      mem = t;
   }
};

int main() {
   V<int> v;
   v.f(42);
   int i = v;
   i += v;
   System::Console::WriteLine(i == (42 * 2) );
}

Output

  

Un costruttore la conversione accetta un tipo e utilizzarlo per creare un oggetto.Un costruttore la conversione viene chiamato con un'inizializzazione diretta solo; i cast non comporta convertire i costruttori.Per impostazione predefinita, convertendo i costruttori sia esplicito per i tipi CLR.

// clr_udc_converting_constructors.cpp
// compile with: /clr
public ref struct R {
   int m;
   char c;

   R(int i) : m(i) { }
   R(char j) : c(j) { }
};

public value struct V {
   R^ ptr;
   int m;

   V(R^ r) : ptr(r) { }
   V(int i) : m(i) { }
};

int main() { 
   R^ r = gcnew R(5);

   System::Console::WriteLine( V(5).m);
   System::Console::WriteLine( V(r).ptr);
}

Output

  

In questo esempio, una funzione statica implicita di conversione eseguita la stessa operazione come costruttore di conversione esplicito.

public value struct V {
   int m;
   V(int i) : m(i) {}
   static operator V(int i) {
      V v(i*100);
      return v;
   }
};

public ref struct R {
   int m;
   R(int i) : m(i) {}
   static operator R^(int i) {
      return gcnew R(i*100);
   }
};

int main() {
   V v(13);   // explicit
   R^ r = gcnew R(12);   // explicit

   System::Console::WriteLine(v.m);
   System::Console::WriteLine(r->m);

   // explicit ctor can't be called here: not ambiguous
   v = 5;
   r = 20;

   System::Console::WriteLine(v.m);
   System::Console::WriteLine(r->m);
}

Output

  

Vedere anche

Riferimenti

Classi e struct (Estensioni del componente C++)