静态强制转换 - 无法通过虚拟继承进行强制转换
Static cast - Cannot cast through virtual inheritance
我正在阅读有关静态和动态强制转换以及它们之间的差异的信息。它指出
static_cast无法通过虚拟继承进行强制转换,但无论如何动态 铸罐。
如果有人能用一个简单的例子来澄清这意味着什么,我将不胜感激。谢谢
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);
动态强制转换可以跨层次结构进行强制转换(或检查为派生类型),而静态强制转换只能在层次结构中上下转换,除了对象实际属于目标类型之外,静态可证明声音。
在可能的情况下,编译器将动态强制转换减少为静态强制转换以提高效率。
static_cast
,当应用于指针或引用时,允许您以不同的方式处理地址。这适用于单个继承,但不适用于多个继承(无论是否虚拟)。
让我们创建一个没有虚拟继承的简单多重继承。
class A1 {virtual ~A1 {}}
class A2 {virtual ~A2 {}}
class B : public A1, public A2 {virtual ~B {}}
类型 B
的对象可以像这样布置在内存中:
+----------------------+|A1 内存占用量 |+----------------------+|A2 内存占用量 |+----------------------+|B 内存占用 |+----------------------+
让我们创建一个 B 类型的对象和一些指向它的指针。
B b;
B* bPtr = &b;
A1* a1Ptr = bPtr;
A1* a2Ptr = bPtr;
bPtr
和 a1Ptr
指向整个B
对象的开头。 a2Ptr
指向对象的A2
部分。
bPtra1Ptr -> +----------------------+ |A1 内存占用量 |a2Ptr -> +----------------------+ |A2 内存占用量 | +----------------------+ |B 内存占用 | +----------------------+
现在,如果您决定使用 static_cast
从 a1Ptr
获取B*
,例如:
B* bPtr2 = static_cast<B*>(a1Ptr);
然后,bPtr2
指向整个B
对象的开始,这很好,但只是巧合。
bPtr2 -> +----------------------+ |A1 内存占用量 | +----------------------+ |A2 内存占用量 | +----------------------+ |B 内存占用 | +----------------------+
但是,如果您决定使用 static_cast
从 a2Ptr
获取B*
,它将指向对象的A2
部分的开头,这是错误的。
B* bPtr3 = static_cast<B*>(a2Ptr); // Points to the wrong block of memory.
+----------------------+ |A1 内存占用量 |bPtr3 -> +----------------------+ |A2 内存占用量 | +----------------------+ |B 内存占用 | +----------------------+
多个但虚拟继承的对象布局略有不同。
假设您有:
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 内存占用量 |+----------------------+|L2 内存占用 |+----------------------+|L3 内存占用 |+----------------------+|L4 内存占用 |+----------------------+
如果您尝试对L2*
执行static_cast
或L3*
以L4*
,则很可能会遇到相同类型的问题。
dynamic_cast
通过在运行时使用 RTTI 避免了static_cast
的问题,并返回正确的地址。
相关文章:
- 虚拟成员函数的定义是否强制在同一转换单元中动态初始化静态数据成员?
- 虚拟地将结构向量转换为结构成员的向量
- 即使基类属性在完成向下转换时是虚拟的,是否有效
- 使用虚拟基类C++向下转换
- 如何将UCHAR虚拟密钥代码转换为std::string
- 虚拟多重继承和强制转换
- 将虚拟地址的逻辑地址转换为物理地址
- C++从基类调用派生类中的函数,而不进行强制转换,也不使用虚拟方法
- 在C++中,是否允许强制转换为仅添加非虚拟方法的派生类
- 可以安全地使用静态强制转换,为每个实例使用唯一的虚拟 int type() 来提高性能
- 在多重虚拟继承的情况下进行强制转换
- 如何使用基类指针调用派生类非虚拟成员函数,而无需类型转换和使用多态性
- 虚拟派生和转换模棱两可
- std::使用虚拟呼叫操作员转换抛出"global functions do not have 'this' pointers"
- 是将基类强制转换为派生类更好,还是在基类上创建一个虚拟函数更好
- 同名类之间的共享 vtables:强制转换为基类型时,对虚拟方法的调用崩溃
- 无法从虚拟键代码转换为 unicode
- 具有虚拟性的多层层次结构可以防止强制转换函数指针
- 虚拟继承(菱形)-为什么我需要从最派生的类向上转换为基类
- 将派生的虚拟重写强制转换为基纯虚拟成员