C++从成员指针强制转换为持有类指针

gal*_*tte 4 c++ casting class member

我有以下课程:

class SSVec
{
public:
    float values[8];
}
Run Code Online (Sandbox Code Playgroud)

我有一个对象SSVec obj,我将float*指针传递obj.values给另一个函数.在代码的其他地方,我得到这个float*指针,然后用魔杖将它强制转换为SSVec*指针.

这是否可能以C++标准定义的行为方式?大部分时间这都适用于静态演员,但我的猜测是它实际上是未定义的行为.

这样做的原因是float*指针传入和传出DLL,它对SSVec一无所知.我保证传递的指针始终指向SSVec :: value [8]对象成员.

该类可能更复杂,但它不是从任何东西派生,没有虚函数,只包含POD类型.values是第一个成员

问题可以重新制定:班级地址和第一个成员地址是否保证是相同的static_cast?

lee*_*mes 6

如果SSVec是POD类型,则定义行为.在为您的类型实现特殊的强制转换函数时,您可以静态断言:

SSVec* SSVec_cast(float* ptr) {
    // Break if someone changes SSVec to be no POD anymore:
    static_assert(std::is_pod<SSVec>::value, "SSVec is no longer a POD!");

    // Break if someone changes SSVec to contain more than the array:
    // [ NOTE: This is optional. Behavior is still defined if the structure
    //   changes(*), but then only if the pointer really points into an SSVec.
    //   With these assertions included, you can even cast from a different
    //   float array of size 8, even if it hasn't been declared as a SSVec. ]
    static_assert(sizeof(SSVec) == 8 * sizeof(float), "SSVec has wrong size!");
    static_assert(sizeof(SSVec::values) == sizeof(SSVec), "SSVec has wrong structure!");
    static_assert(offsetof(SSVec, values) == 0, "SSVec has wrong structure!");

    // Now it is safe to reinterpret cast the pointer:
    // [ (*) NOTE: If above assertions are removed, please change (ptr)
    //   to (reinterpret_cast<char*>(ptr) - offsetof(SSVec, values)). ]
    return reinterpret_cast<SSVec*>(ptr);
}
Run Code Online (Sandbox Code Playgroud)

通过重载可以使用const指针完成相同的操作; 当然,您可以将这些断言移动到某个共同功能或全局范围(最好).


PS:请看看std::array.它完全符合您的要求:

typedef std::array<float,8> SSVec;
Run Code Online (Sandbox Code Playgroud)