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_cast
atama safe_cast
veya ; 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);
}