通过void*强制转换为基
Casting to base via void*
这是未定义行为吗?
class Derived: public Base //No other bases!!!
{
//...
};
Derived d;
void *pv = &d;
Base *b = static_cast<Base*>(pv);
b->SomeMethod();
在合理的实现中,只要存在单继承,Base
和Derived
指针的位就会匹配。但是语言能保证这一点吗?
编辑:真正的目的是通过C层将指向多态c++对象的指针传递回c++回调。该对象创建为Derived,但在上述回调中作为Base使用。
是,你所做的实际上调用未定义行为。
标准要求保证从T*
到void*
再铸回T*
是安全的,后者的T*
将保持与原来的T*
相同的值。
5.29 静态强制转换
[expr.static.cast]
<一口> 13 一口> <子>…对象指针类型的值转换为"指向cvvoid的指针"并返回,可能具有不同的cv-限定条件,应保持其原始值。"。子>
上述行为保证T * p = static_cast<T*> (static_cast<void*> (some_T_ptr))
将在p
中产生一个值,使得p == some_p
.
在你的例子中,我们从void*
转换到与原始T
相关的类型,但它不是完全相同的T
;这意味着操作的结果是未指定的。
编译器可以安全地假设void*
指针(pv
)中的地址最初指向Base
,因此它不会做任何偏移修改来适当地调整我们从Derived*
到Base*
,而不是从Base*
到Base*
。
编译器可以简单地将pv
的值复制到b
中,当它真正应该调整这个值时,因为它来自Derived
的地址。
Derived * pd = &some_derived;
void * pv = static_cast<void*> (pd);
Base * pb = static_cast<Base*> (pv); // unsafe
关于
在合理的实现中,只要存在单继承,基指针和派生指针的位就应该匹配。”
对于简单类型是,但是不当基是非多态且派生引入了虚成员时。
因此,将Derived*
转换为void*
,然后直接转换为Base*
是未定义行为,不仅在形式上是学院式的,而且在实践中也是如此。
如果p
的静态已知类型是指向多态对象的指针,那么特殊类型转换dynamic_cast<void*>( p )
将给您一个指向最派生对象的指针。
这对于使用像std::unordered_map
这样的哈希表是很有用的。
此外,可能与您的实际目的有关,该标准保证指向POD类型的第一个成员的指针可以被强制转换为指向该类型的指针,反之亦然。
- 为什么这个函数将"const char*"转换为"void* const"而不是"const void*"
- 将尾部调用void(i32,..)位转换为llvm::函数以获取FnAttribute
- 为什么在逗号分隔符上下文中将预增量的结果强制转换为void
- Boost buffer_cast 无法从 void* 转换为 PointerToPodType
- 将通用引用强制转换为可调用的 void 指针,反之亦然
- 为什么在将 void 指针转换为整数指针时出现分段错误
- 在不同的编译器上转换为 void**
- 当我使用 void 函数的返回值(通过强制转换函数指针)时,究竟会发生什么?
- 不能在 if 语句 - c++ 中使用 void func 直接将字符串转换为大写
- 是否可以将已经初始化的变量转换为 void*?
- 错误:从'void*'到'const uint8_t* {aka const unsigned char*}'的转换无效 [-允许]
- 将可变参数模板类型转换为 void,预期')'之前
- 如何在运行时将指向派生类的 void* 正确转换为指向基类的 void*
- 是否强制转换void**并将第一个字节设置为nullptr
- 如何转换 void* 以访问结构的静态数据成员?
- 警告传递"double"以转换"void moveto(int, int)"的 2
- 是否有一种方法可以自动转换void指针的类型
- 在构造函数中强制转换void*并访问值
- 重新解释不带类型标识符的强制转换void
- 强制转换void指针