C++ 在void指针之间来回转换QObject是否会丢失数据?

C++ 在void指针之间来回转换QObject是否会丢失数据?,c++,qt,void-pointers,C++,Qt,Void Pointers,我试图将我的对象投射到空指针上或从空指针上投射 这就是我的类继承的方式: #ifndef EVERYTHING_H #define EVERYTHING_H #include <QString> #include <QObject> struct Base { public: const QString name; explicit Base(const QString& n) : name { n } {} };

我试图将我的对象投射到空指针上或从空指针上投射

这就是我的类继承的方式:

#ifndef EVERYTHING_H
#define EVERYTHING_H
 
#include <QString>
#include <QObject>
 
struct Base
{
public:
    const QString name;
    explicit Base(const QString& n)
        : name { n } {}
};
      
class A : public QObject, public Base
{
    Q_OBJECT
 
public:
    explicit A(QObject *parent = nullptr)
        : QObject(parent),
          Base("name") {}
};
 
#endif // EVERYTHING_H
  • 我不明白为什么第一个
    aa
    与原始指针的地址不同,并且可以工作,而第二个
    aa
    突然指向原始地址,但不工作
  • 常量数据是如何丢失的?在我的实际应用程序中(不是这个最小的示例),我没有得到一个空字符串,而是一个断言错误:
  • 断言:“size==0 | | offset<0 | | size|u t(offset)>=sizeof(QArrayData)”


    注意:如果一个不是QObject(只是Base),一切都正常,每次我都会得到“name”。

    我需要先从A到Base,然后从Base到void,然后再从void到Base。浇铸的顺序显然需要颠倒。

    我需要先从A浇铸到底部,然后从底部浇铸到空隙,然后再从空隙浇铸到底部。强制转换的顺序显然需要颠倒。

    在继承层次结构上下强制转换指针时,不能保证指针中的底层内存地址保持不变。根据涉及的继承细节,可能需要进行调整,以确保生成的指针最终指向对象的适当部分。(例如,这种情况可能发生在多重继承中。)

    通常情况下,编译器会为您处理这些细节,但当您涉及
    void*
    时,编译器将无法知道发生了什么。所以,正确地做事完全取决于你

    在这种情况下:

    A *a = new A();
    auto aa = static_cast<Base*>(a);
    
    编译器获取
    a
    中的内存地址,将其直接复制到
    v
    ,然后将其直接复制到
    aa
    。没有进行任何调整。因此,通过颠覆编译器的类型知识,您最终遇到了一个问题

    我很确定我听说过,你应该只从
    void*
    返回到最初被铸造到
    void*
    的确切类型。这种情况就是一个例子。因此,如果我们改变它:

    A *a = new A();
    void* v = static_cast<void*>(a);
    A* aa = static_cast<A*>(v);
    Base* base = static_cast<Base*>(aa);
    
    A*A=newa();
    void*v=静态铸件(a);
    A*aa=静态_型铸造(v);
    底座*底座=静态铸件(aa);
    

    然后您会发现它是有效的。

    在继承层次结构上下转换指针时,不能保证指针中的底层内存地址保持不变。根据涉及的继承细节,可能需要进行调整,以确保生成的指针最终指向对象的适当部分。(例如,这种情况可能发生在多重继承中。)

    通常情况下,编译器会为您处理这些细节,但当您涉及
    void*
    时,编译器将无法知道发生了什么。所以,正确地做事完全取决于你

    在这种情况下:

    A *a = new A();
    auto aa = static_cast<Base*>(a);
    
    编译器获取
    a
    中的内存地址,将其直接复制到
    v
    ,然后将其直接复制到
    aa
    。没有进行任何调整。因此,通过颠覆编译器的类型知识,您最终遇到了一个问题

    我很确定我听说过,你应该只从
    void*
    返回到最初被铸造到
    void*
    的确切类型。这种情况就是一个例子。因此,如果我们改变它:

    A *a = new A();
    void* v = static_cast<void*>(a);
    A* aa = static_cast<A*>(v);
    Base* base = static_cast<Base*>(aa);
    
    A*A=newa();
    void*v=静态铸件(a);
    A*aa=静态_型铸造(v);
    底座*底座=静态铸件(aa);
    

    然后你会发现它是有效的。

    QObject和template类实际上与这个问题相关吗?换句话说,如果
    A
    只是直接从
    Base
    派生而来,而没有其他东西,你还会有同样的问题吗?@JarMan我想我不会,但我确实会。刚刚测试过。在没有模板的情况下也是一样,我编辑了这个问题。@JarMan刚刚测试过,如果一个不是QObject,问题就会消失。所以它与Qt有关。但是,它必须是QoObject。。。我想这个问题更可能是由于多重继承,而不是QObject造成的。@JarMan我需要先从A到B,然后从B到D,然后再从D到B。喜欢相同的顺序,但相反QObject和template类是否与问题实际相关?换句话说,如果
    A
    只是直接从
    Base
    派生而来,而没有其他东西,你还会有同样的问题吗?@JarMan我想我不会,但我确实会。刚刚测试过。在没有模板的情况下也是一样,我编辑了这个问题。@JarMan刚刚测试过,如果一个不是QObject,问题就会消失。所以它与Qt有关。但是,它必须是QoObject。。。我想这个问题更可能是由于多重继承,而不是QObject造成的。@JarMan我需要先从A到B,然后从B到D,然后再从D到B。喜欢相同的顺序,但相反我已经猜出来了,但你的答案解释了为什么你已经猜出来了,但你的答案解释了为什么
    A *a = new A();
    void* v = static_cast<void*>(a);
    A* aa = static_cast<A*>(v);
    Base* base = static_cast<Base*>(aa);