我正在阅读静态和动态演员以及他们之间的差异。 它说明了
static_cast不能通过虚拟继承来强制转换 演员可以。
如果有人能用一个简单的例子澄清这意味着什么,我将不胜感激。感谢
答案 0 :(得分:1)
class A {virtual ~A {}}
class B {virtual ~B {}}
class C : A, B {}
C o;
// Now, some implicit conversions:
A& a = c;
B& b = c;
// static casts back:
C& ca = static_cast<C>(a);
C& cb = static_cast<C>(b);
// dynamic casts over the type:
A& ab = dynamic_cast<A>(b);
B& ba = dynamic_cast<B>(a);
动态强制转换可以在层次结构中进行转换(或检查为派生类型),而静态强制转换只能在层次结构中上下移动,除了对象实际上是目标类型之外,其中静态可保持声音。
在可能的情况下,编译器会将动态强制转换为静态转换以提高效率。
答案 1 :(得分:1)
static_cast
,当应用于指针或引用时,允许您以不同方式处理地址。这适用于单继承,但不适用于多重继承(无论是否为虚拟)。
让我们创建一个没有虚拟继承的简单多重继承。
class A1 {virtual ~A1 {}}
class A2 {virtual ~A2 {}}
class B : public A1, public A2 {virtual ~B {}}
B
类型的对象可以像这样在内存中布局:
+----------------------+ | A1 memory footprint | +----------------------+ | A2 memory footprint | +----------------------+ | B memory footprint | +----------------------+
让我们创建一个B类型的对象和一些指向它的对象。
B b;
B* bPtr = &b;
A1* a1Ptr = bPtr;
A1* a2Ptr = bPtr;
bPtr
和a1Ptr
指向整个B
对象的开头。 a2Ptr
指向对象的A2
部分。
bPtr a1Ptr -> +----------------------+ | A1 memory footprint | a2Ptr -> +----------------------+ | A2 memory footprint | +----------------------+ | B memory footprint | +----------------------+
现在,如果您决定使用static_cast
从B*
获取a1Ptr
,例如:
B* bPtr2 = static_cast<B*>(a1Ptr);
然后,bPtr2
指向整个B
对象的开头,这很好,但只是巧合。
bPtr2 -> +----------------------+ | A1 memory footprint | +----------------------+ | A2 memory footprint | +----------------------+ | B memory footprint | +----------------------+
但是,如果您决定使用static_cast
从B*
获取a2Ptr
,则会指向对象的A2
部分的开头,错。
B* bPtr3 = static_cast<B*>(a2Ptr); // Points to the wrong block of memory.
+----------------------+ | A1 memory footprint | bPtr3 -> +----------------------+ | A2 memory footprint | +----------------------+ | B memory footprint | +----------------------+
多个但虚拟继承的对象布局略有不同。
说你有:
class L1 {virtual ~L1();};
class L2 : public virtual L1 {virtual ~L2();};
class L3 : public virtual L1 {virtual ~L3();};
class L4 : public L2, public L3 {virtual ~L4();};
L4
类型对象的布局如下所示:
+----------------------+ | L1 memory footprint | +----------------------+ | L2 memory footprint | +----------------------+ | L3 memory footprint | +----------------------+ | L4 memory footprint | +----------------------+
如果您尝试在static_cast
或L2*
至L3*
上执行L4*
,则很可能遇到相同类型的问题。
dynamic_cast
在运行时使用RTTI避免了static_cast
的问题,并返回正确的地址。