【发布时间】:2011-01-04 04:32:02
【问题描述】:
正如您在下面的代码中看到的,我有一个抽象基类“HostWindow”,以及从它派生的类“Chrome”。所有功能都在 Chrome 中实现。问题是,如果 Chrome 是虚拟函数,我无法调用它们。
class HostWindow : public Noncopyable {
public:
virtual ~HostWindow() { }
// Pure virtual functions:
virtual void repaint(const IntRect&, bool contentChanged, bool immediate = false, bool repaintContentOnly = false) = 0;
virtual void scrollbarsModeDidChange() const = 0;
}
class Chrome : public HostWindow {
// HostWindow functions:
virtual void repaint(const IntRect&, bool contentChanged, bool immediate = false, bool repaintContentOnly = false);
virtual void scrollbarsModeDidChange() const;
void focus() const;
}
假设我们有一个 Chrome 实例,我们调用了几个函数:
WebCore::Chrome *chrome = new Chrome();
chrome->repaint(IntRect(), true); // Null pointer error
chrome->focus(); // returns void (works)
每当我调用虚函数时,我得到的空指针错误是:
程序接收到信号EXC_BAD_ACCESS,无法访问内存。 原因:KERN_PROTECTION_FAILURE 地址:0x00000008
知道发生了什么吗?
更新: 正如你们中的许多人指出的那样——这段代码实际上是运行的。不幸的是,我无法提供更完整的示例,因为代码在 WebCore (WebKit) 内部很深。但是,我已经缩小了问题的范围。如果我手动创建一个 Chrome 实例,调用虚拟函数就可以了。所以问题出在这个特定的 chrome 实例上——它无法正确实例化。现在,Chrome 实例在另一个类的构造函数中实例化。我会进一步调查...
更新 2: 好的,检查有问题的实例上的 vtable 表明它是空的;来自 GDB:
p *(void **)chrome
$52 = (void *) 0x0
一个普通的实例有一个正确的 vtable。所以,我必须弄清楚为什么 vtable 是 nil - 我想知道这怎么会发生?也许是因为它在其他一些构造函数类中被实例化?
更新 3: 看起来我对这个问题是正确的,因为它是在另一个类的构造函数中实例化。
所以,在实例化之前是这样的:
Page::Page(ChromeClient* chromeClient, ...)
: m_chrome(new Chrome(this, chromeClient))
而 m_chrome 是一个无效的实例,具有一个 nil vtable。 我已经更改了实例化,因此它在第一次需要变量时发生(这涉及保存 ChromeClient 以供以后使用):
Page::Page(ChromeClient* chromeClient, ...)
: m_chrome(0)
, m_chrome_client(chromeClient)
Chrome* Page::chrome() const {
if(!m_chrome) {
m_chrome = new Chrome(this, m_chrome_client);
}
return m_chrome;
}
现在 Page::chrome() 实例是正确的,具有正确的 vtable - 相当奇怪!
更新 4: 最后更新,我保证:)。好的,所以我已经准确地指出了它。如果您在 Page 构造函数的主体中实例化它,您将使用 vtable 获得正确的实例。如果您在 Page 构造函数的头部实例化它,它就没有 vtable。您可以在构造函数的头脑中进行的变量设置类型是否有任何限制?我想这是另一个 Stackoverflow 问题。
感谢大家的帮助。
【问题讨论】:
-
请使用复制和粘贴发布真实代码。
-
这是真正的代码。我不能让它更简洁,因为它就在 WebKit 的中间。
-
在调用 'WebCore::Chrome *chrome = new Chrome();' 之后,'chrome' 的值是多少?如果为NULL,是否抛出异常?
-
不为空。我正在检查 gdb。
-
请确保您的代码在发布之前可以正常工作。我们没有义务重新编写您的代码,以便在尝试解决您的问题之前进行编译...
标签: c++ inheritance polymorphism abstract-class abc