C++ 处理不相关类型的动态强制转换 #包括 使用名称空间std; 类X{ 公众: 虚空f(){} }; 类Y{ 公众: 虚空g(){} }; int main() { X*X=新的X(); Y*Y=动态_投射(x);//A //Y*Y=静态_投射(x);//B cout
编译器不在乎,因为它是C++ 处理不相关类型的动态强制转换 #包括 使用名称空间std; 类X{ 公众: 虚空f(){} }; 类Y{ 公众: 虚空g(){} }; int main() { X*X=新的X(); Y*Y=动态_投射(x);//A //Y*Y=静态_投射(x);//B cout,c++,inheritance,C++,Inheritance,编译器不在乎,因为它是动态强制转换,y将在强制转换后NULL。动态强制转换使用运行时类型信息。因此这种情况是合法的,但它将返回NULL指针。 静态强制转换由编译器进行评估。dynamic\u cast在运行时使用RTTI执行类型检查,而static\u cast在编译时执行类型检查。因此,如果运行A将得到y==NULL 我建议您在C++类型的转换上使用.< /P> < P>动态CAST如果不能完成转换,返回null: 并搜索动态强制转换如果[通过使用动态强制转换]尝试强制转换为指针类型,而该类
动态强制转换
,y
将在强制转换后NULL
。动态强制转换使用运行时类型信息。因此这种情况是合法的,但它将返回NULL指针。
静态强制转换由编译器进行评估。
dynamic\u cast
在运行时使用RTTI执行类型检查,而static\u cast
在编译时执行类型检查。因此,如果运行A
将得到y==NULL
我建议您在C++类型的转换上使用.< /P> < P>动态CAST如果不能完成转换,返回null:
并搜索动态强制转换如果[通过使用动态强制转换]尝试强制转换为指针类型,而该类型不是参数对象的实际类型,则强制转换的结果将为NULL
#include <iostream>
using namespace std;
class X{
public:
virtual void f(){}
};
class Y {
public:
virtual void g() {}
};
int main()
{
X * x = new X();
Y* y = dynamic_cast<Y*>(x); //A
// Y* y = static_cast<Y*>(x); //B
cout << y << endl;
}
Y*Y=dynamic_cast(x);//NULL,因为'x'不是'Y'`
这就是为什么不相关类型之间允许使用动态\u cast
:
Y* y = dynamic_cast<Y*>(x); // NULL because `X` is not a `Y`
X类{
公众:
虚空f(){}
};
类Y{
公众:
虚空g(){}
};
Z类:公共X,公共Y{};
int main()
{
X*X=新的Z();
Y*Y=dynamic_cast(x);//编译并生成非空指针
}
静态强制转换与动态强制转换之间存在巨大差异,我将把讨论范围缩小到对象世界
(声名狼藉的)向上投射可使用静态投射。即:
class X{
public:
virtual void f(){}
};
class Y {
public:
virtual void g() {}
};
class Z : public X, public Y {};
int main()
{
X* x = new Z();
Y* y = dynamic_cast<Y*>(x); // compiles and yields non-null pointer
}
这将产生一个错误:编译器不知道您来自哪个基(来自D1
的基或来自D2
的基)
或者如果您使用了virtual
继承:
struct Base {};
struct D1: Base {};
struct D2: Base {};
struct Derived: D1, D2 {};
编译器需要运行时信息,因此编译也会失败
然而,dynamic\u cast
要聪明得多,尽管这是以运行时开销为代价的。编译器生成关于对象的信息,通常称为RTTI(运行时类型信息),dynamic\u cast
将探索这些信息以允许:
强制转换取决于真正的运行时类型:
struct VDerived: virtual VBase {};
请注意,如果由于层次结构(如上面的D1
/D2
示例)而存在歧义,则这仍然不起作用
struct VDerived: virtual VBase {};
// will throw `bad_cast` if b is not a `Derived`
void foo(Base& b) { Derived& d = dynamic_cast<Derived&>(b); }
struct X {};
struct Y {};
void foo(X* x) { Y* y = dynamic_cast<Y*>(x); }
// If I add:
struct Z: X, Y {};
// then if x is in fact a Z, y will be non-null
void bar(VBase* vb) { VDerived* vd = dynamic_cast<VDerived*>(vb); }
void foobar(X* x)
{
void* xAddr = dynamic_cast<void*>(x);
Y* y = dynamic_cast<Y*>(y);
void* yAddr = dynamic_cast<void*>(y);
Z* z = dynamic_cast<Z*>(x);
void* zAddr = dynamic_cast<void*>(z);
if (z) { assert(xAddr == yAddr && xAddr == zAddr); }
}