Aracılığıyla paylaş


Nasıl yapılır: C++/CLI üzerinde safe_cast kullanma

Bu makalede, C++/CLI uygulamalarında safe_cast nasıl kullanılacağı gösterilmektedir. C++/CX'teki safe_cast hakkında bilgi için bkz . safe_cast.

Yayına Alma

Yukarı yayın, türetilmiş bir türden temel sınıflarından birine türetilmiş bir atamadır. Bu atama güvenlidir ve açık bir atama gösterimi gerektirmez. Aşağıdaki örnek, safe_cast bir upcast işleminin onunla ve olmadan nasıl gerçekleştirebileceğinizi gösterir.

// safe_upcast.cpp
// compile with: /clr
using namespace System;
interface class A {
   void Test();
};

ref struct B : public A {
   virtual void Test() {
      Console::WriteLine("in B::Test");
   }

   void Test2() {
      Console::WriteLine("in B::Test2");
   }
};

ref struct C : public B {
   virtual void Test() override {
      Console::WriteLine("in C::Test");
   };
};

int main() {
   C ^ c = gcnew C;

   // implicit upcast
   B ^ b = c;
   b->Test();
   b->Test2();

   // upcast with safe_cast
   b = nullptr;
   b = safe_cast<B^>(c);
   b->Test();
   b->Test2();
}
in C::Test
in B::Test2
in C::Test
in B::Test2

Aşağı Yayın

Downcast, temel sınıftan temel sınıftan türetilen bir sınıfa yapılan atamadır. Downcast yalnızca çalışma zamanında ele alınan nesne gerçekten türetilmiş bir sınıf nesnesine hitap ediyorsa güvenlidir. safe_cast aksinestatic_cast, dinamik bir denetim gerçekleştirir ve dönüştürme başarısız olursa oluştururInvalidCastException.

// safe_downcast.cpp
// compile with: /clr
using namespace System;

interface class A { void Test(); };

ref struct B : public A {
   virtual void Test() {
      Console::WriteLine("in B::Test()");
   }

   void Test2() {
      Console::WriteLine("in B::Test2()");
   }
};

ref struct C : public B {
   virtual void Test() override {
      Console::WriteLine("in C::Test()");
   }
};

interface class I {};

value struct V : public I {};

int main() {
   A^ a = gcnew C();
   a->Test();
   B^ b = safe_cast<B^>(a);
   b->Test();
   b->Test2();

   V v;
   I^ i = v;   // i boxes V
   V^ refv = safe_cast<V^>(i);

   Object^ o = gcnew B;
   A^ a2= safe_cast<A^>(o);
}
in C::Test()
in C::Test()
in B::Test2()

Kullanıcı tanımlı dönüştürmelerle safe_cast

Sonraki örnek, kullanıcı tanımlı dönüştürmeleri çağırmak için nasıl kullanabileceğinizi safe_cast gösterir.

// safe_cast_udc.cpp
// compile with: /clr
using namespace System;
value struct V;

ref struct R {
   int x;
   R() {
      x = 1;
   }

   R(int argx) {
      x = argx;
   }

   static operator R::V^(R^ r);
};

value struct V {
   int x;
   static operator R^(V& v) {
      Console::WriteLine("in operator R^(V& v)");
      R^ r = gcnew R();
      r->x = v.x;
      return r;
   }

   V(int argx) {
      x = argx;
   }
};

   R::operator V^(R^ r) {
      Console::WriteLine("in operator V^(R^ r)");
      return gcnew V(r->x);
   }

int main() {
   bool fReturnVal = false;
   V v(2);
   R^ r = safe_cast<R^>(v);   // should invoke UDC
   V^ v2 = safe_cast<V^>(r);   // should invoke UDC
}
in operator R^(V& v
in operator V^(R^ r)

safe_cast ve kutulama işlemleri

Kutulama

Kutulama, derleyici tarafından eklenen, kullanıcı tanımlı bir dönüştürme olarak tanımlanır. Bu nedenle, CLR yığınındaki bir değeri kutuya almak için kullanabilirsiniz safe_cast .

Aşağıdaki örnekte basit ve kullanıcı tanımlı değer türleriyle kutulama gösterilmektedir. Yerel safe_cast yığında bulunan bir değer türü değişkenini kutular, böylece çöp toplanan yığındaki bir değişkene atanabilir.

// safe_cast_boxing.cpp
// compile with: /clr
using namespace System;

interface struct I {};

value struct V : public I {
   int m_x;

   V(int i) : m_x(i) {}
};

int main() {
   // box a value type
   V v(100);
   I^ i = safe_cast<I^>(v);

   int x = 100;
   V^ refv = safe_cast<V^>(v);
   int^ refi = safe_cast<int^>(x);
}

Sonraki örnek, bir işlemdeki safe_cast kullanıcı tanımlı dönüştürmeye göre kutulamanın önceliğe sahip olduğunu gösterir.

// safe_cast_boxing_2.cpp
// compile with: /clr
static bool fRetval = true;

interface struct I {};
value struct V : public I {
   int x;

   V(int argx) {
      x = argx;
   }

   static operator I^(V v) {
      fRetval = false;
      I^ pi = v;
      return pi;
   }
};

ref struct R {
   R() {}
   R(V^ pv) {}
};

int main() {
   V v(10);
   I^ pv = safe_cast<I^>(v);   // boxing will occur, not UDC "operator I^"
}

Kutulama

Kutu açma, derleyici tarafından eklenen, kullanıcı tanımlı bir dönüştürme olarak tanımlanır. Bu nedenle, CLR yığınındaki bir değerin kutusunu açmak için kullanabilirsiniz safe_cast .

Kutu açma kullanıcı tanımlı bir dönüştürmedir, ancak kutulamadan farklı olarak, kutulamanın açık olması gerekir; başka bir deyişle, , C stilinde bir static_castatama safe_castveya ; kutu açma örtük olarak gerçekleştirilemez.

// safe_cast_unboxing.cpp
// compile with: /clr
int main() {
   System::Object ^ o = 42;
   int x = safe_cast<int>(o);
}

Aşağıdaki örnekte değer türleri ve ilkel türler içeren kutulamanın kaldırılma durumu gösterilmektedir.

// safe_cast_unboxing_2.cpp
// compile with: /clr
using namespace System;

interface struct I {};

value struct VI : public I {};

void test1() {
   Object^ o = 5;
   int x = safe_cast<Int32>(o);
}

value struct V {
   int x;
   String^ s;
};

void test2() {
   V localv;
   Object^ o = localv;
   V unboxv = safe_cast<V>(o);
}

void test3() {
   V localv;
   V^ o2 = localv;
   V unboxv2 = safe_cast<V>(o2);
}

void test4() {
   I^ refi = VI();
   VI vi  = safe_cast<VI>(refi);
}

int main() {
   test1();
   test2();
   test3();
   test4();
}

safe_cast ve genel türler

Sonraki örnek, genel bir türle aşağı yayın gerçekleştirmek için nasıl kullanabileceğinizi safe_cast gösterir.

// safe_cast_generic_types.cpp
// compile with: /clr
interface struct I {};

generic<class T> where T:I
ref struct Base {
   T t;
   void test1() {}
};

generic<class T> where T:I
ref struct Derived:public Base <T> {};

ref struct R:public I {};

typedef Base<R^> GBase_R;
typedef Derived<R^> GDerived_R;

int main() {
   GBase_R^ br = gcnew GDerived_R();
   GDerived_R^ dr = safe_cast<GDerived_R^>(br);
}

Ayrıca bkz.

safe_cast