gpt4 book ai didi

C++:通过派生类调用重载虚拟,导致 NULL 调用/段错误

转载 作者:太空宇宙 更新时间:2023-11-04 11:25:52 24 4
gpt4 key购买 nike

预计到达时间:

我终于抽出时间在另一台机器上运行相同的代码,而且它工作得很好。我实际上不太确定它原来是什么机器,可能是 linux 笔记本或 macbook air。这一次,它是一些运行 debian 的托管虚拟机。

看起来我真的遇到了一个晦涩的编译器或硬件错误,听起来很奇怪而且不可能。不过,我认为不值得进一步调查。

原始问题:

我有一个周末项目/玩具小部件集。

基类 Widget 中有一个虚函数 calculateContentRect(),它从 中的非虚函数 calculateRects() 调用>Widget 来计算一些矩形。然后在派生类 Window 中覆盖虚函数(但在进一步派生类 PopupMenu 中不覆盖)。

当我实例化WidgetWindow 时,一切正常。但是,如果我实例化一个 PopupMenu,从 calculateRect() 调用 calculateContentRect() 会失败,gdb 会告诉我它正在尝试调用 NULL - 类似于 (gdb) 的内容:

#0  0x0000000000000000 in Window::calculateContentRect()
#1 0xWHATEVER in Widget::calculateRects()

请注意,这不是基类指针。这一切都发生在堆栈上。

我无法隔离和重现该错误,但我不能很好地将该死的整个项目粘贴到这里,所以我正在尝试删除相关部分...

所以,这是简化的代码片段:

class Widget {
protected:
void calculateRects() { ... calculateContentRect(); }
virtual void calculateContentRect() { ... }
};

class FocusableContainer: public Widget { ... };

class Window: public FocusableContainer {
protected:
virtual void calculateContentRect() { ... }
};

class PopupMenu: public Window {
public:
void pack() { ... calculateRects(); ... }
};

int main() {
PopupMenu pm(...);
pm.pack();
}

简而言之,我认为/希望以下是一些相关的问题:

  • 从理论上讲,不正确构造的对象是否可能导致此类行为(我很确定情况并非如此,但谁知道...)?
  • 可见性对此有影响吗?相互调用的函数都受到保护。
  • 由于该错误仅发生在调用派生派生对象(Widget > Window > PopupMenu)时,是否一定意味着错误出在 PopupMenu 中?
  • vtable 中的条目怎么可能是 0x0?

最佳答案

我遇到了同样的问题。清理/重建帮助了我。我知道这很简单而且很愚蠢,但是我花了半天的时间来尝试这个简单的操作。这很可能对作者没有帮助,但也许可以为其他初级开发人员节省一些时间。

我理解的机制是,当我在祖先类中将某些功能更改为虚拟时,子类没有更改,因此没有重建,最后没有创建 vtable。

关于C++:通过派生类调用重载虚拟,导致 NULL 调用/段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26709997/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com