Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Den här artikeln visar hur du använder safe_cast i C++/CLI-program. Information om safe_cast i C++/CX finns i safe_cast.
Uppcasting
En uppåtriktad typkonvertering är en konvertering av en härledd typ till någon av dess basklasser. Denna typkonvertering är säker och kräver ingen explicit konverteringsnotation. Följande exempel visar hur du utför en uppgradering med safe_cast och utan safe_cast.
// 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
Nedständande
En nedtypning är en typning från en basklass till en klass som är härledd från basklassen. En nedåtriktad typomvandling är endast säker om objektet som refereras vid körning faktiskt refererar till ett objekt av en härledd klass. Till skillnad från static_castutför safe_cast en dynamisk kontroll och genererar InvalidCastException om konverteringen misslyckas.
// 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()
safe_cast med användardefinierade konverteringar
Nästa exempel visar hur du kan använda safe_cast för att anropa användardefinierade konverteringar.
// 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- och boxningsverksamhet
Boxning
Boxning definieras som en konvertering införd av kompilatorn, användardefinierad. Därför kan du använda safe_cast för att boxa ett värde på CLR-heapen.
Följande exempel visar boxning med enkla och användardefinierade värdetyper. En safe_cast boxar en värdetypsvariabel som finns i den inbyggda stacken så att den kan tilldelas till en variabel på den skräpinsamlade minneshögen.
// 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);
}
Nästa exempel visar att boxning har prioritet framför en användardefinierad konvertering i en safe_cast åtgärd.
// 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^"
}
Öppna förpackningen
Unboxing definieras som en kompilatorinmatad, användardefinierad konvertering. Därför kan du använda safe_cast för att ta bort ett värde på CLR-heapen.
Unboxing är en användardefinierad konvertering, men till skillnad från boxning måste unboxing vara explicit, dvs. den måste utföras av en static_cast, typkonvertering i C-stil eller safe_cast; unboxing kan inte utföras implicit.
// safe_cast_unboxing.cpp
// compile with: /clr
int main() {
System::Object ^ o = 42;
int x = safe_cast<int>(o);
}
Följande exempel visar avboxning med värdetyper och primitiva typer.
// 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 och generiska typer
Nästa exempel visar hur du kan använda safe_cast för att utföra en nedtypning med en generisk typ.
// 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);
}