c++ 为什么父类指针在从子指针强制转换到父指针时有错误的数据?

3phpmpom  于 2023-01-06  发布在  其他
关注(0)|答案(1)|浏览(123)

这是我的类层次结构。

class EventA {/* adds itself to list */};
class EventB {/* adds itself to list */};
class EventC {/* adds itself to list */};
class EventD {/* adds itself to list */};

class EventE {/* adds itself to list */};
class EventF {/* adds itself to list */};
class EventG {/* adds itself to list */};
class EventH {/* adds itself to list */};

class Component : public EventA, public EventB, public EventC, public EventD {
    // Propeties and functions
    bool sentinel;
};

class CustomComponent : public Component {
    // Propeties and functions
};

class UserComponent : public CustomComponent, public EventE, public EventF, public EventG, public EventH {
    // Propeties and functions
};

我列出了每种类型:EventEEventFEventGEventH。当我创建UserComponent对象时,它们通过构造函数添加到列表中。我遇到的问题是,当我迭代EventEEventFEventGEventH的列表时,当我从EventEEventG强制转换指针时,EventFEventGEventHComponent*某些属性在解释为这样的指针时是不正确的。例如,有时我的bool sentinel值将是true(216),而它们应该是false。我怀疑当我转换指针时,它没有偏移内存来匹配我所布局的类层次结构。换句话说,我认为它没有从正确的内存地址阅读。有人熟悉这个问题吗?我的问题是在系统设计级别,所以欢迎任何离题的解决方案,或者任何具有不同方法的解决方案。

对要求的最小示例的响应

这段代码是我遇到的问题的一个最小的例子。我按照评论部分的要求提供了它。

#include <iostream>

using namespace std;

class EventA {
    public:
        char a;

        EventA() {
            a = 'a';
        }
        ~EventA() {

        }
};
class EventB {
    public:
        char b;
        
        EventB() {
            b = 'b';
        }
        ~EventB() {

        }
};
class EventC {
    public:
        char c;

        EventC() {
            c = 'c';
        }
        ~EventC() {

        }
};
class EventD {
    public:
        char d;

        EventD() {
            d = 'd';
        }
        ~EventD() {

        }
};

class EventE {
    public:
        char e;
        
        EventE() {
            e = 'e';
        }
        ~EventE() {

        }
};
class EventF {
    public:
        char f;

        EventF() {
            f = 'f';
        }
        ~EventF() {

        }
};
class EventG {
    public:
        char g;

        EventG() {
            g = 'g';
        }
        ~EventG() {

        }
};
class EventH {
    public:
        char h;

        EventH() {
            h = 'h';
        }
        ~EventH() {

        }
};

class Component : public EventA, public EventB, public EventC, public EventD {
    public:
        int customValue;

        Component() {
            customValue = 1000;
        }
        ~Component() {

        }
};

class CustomComponent : public Component {
    public:
        int customComponentValue;

        CustomComponent() {
            customComponentValue = 2000;
        }
        ~CustomComponent() {

        }
};

class UserComponent : public CustomComponent, public EventE, public EventF, public EventG, public EventH {
    public:
        int userComponentValue;

        UserComponent() {
            userComponentValue = 3000;
        }
        ~UserComponent() {

        }
};

int main() {
    UserComponent userComponent = UserComponent();
    EventE* ptrEventE = (EventE*)&userComponent;
    Component* ptrComponent = (Component*)ptrEventE;
    cout << ptrComponent->customValue << endl;
}

如果进入调试模式并检查ptrComponent的值,您将看到我所讨论的内容。请注意,我所做的转换正是在我的系统的不同点上进行的。这就是我这样做的原因。

63lcw9qa

63lcw9qa1#

如果使用static_cast而不是C样式转换,则会捕获此错误:

a.cpp: In function 'int main()':
a.cpp:134:31: error: invalid 'static_cast' from type 'EventE*' to type 'Component*'
  134 |     Component* ptrComponent = static_cast<Component*>(ptrEventE);
      |                               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

EventE不是Component的基类,所以编译器不知道它们是如何连接的,在您的情况下,它们是通过公共派生UserComponent连接的,因为可能还有其他布局不同的公共派生类,所以没有帮助,static_cast在这种情况下抛出错误,C风格的强制转换只执行reinterpret_cast,并假定不需要修改指针。
两种修复方法:或者使Component也从EventE派生,或者通过已知的公共派生类强制转换:

int main() {
    UserComponent userComponent = UserComponent();
    EventE* ptrEventE = static_cast<EventE*>(&userComponent);
    Component* ptrComponent = static_cast<UserComponent*>(ptrEventE);  // UserComponent --> Component is implicit
    cout << ptrComponent->customValue << endl;
}

相关问题