我非常罕见的错误,并了解我需要了解C ++的一些事实的原因。让我解释一下这个问题:
有这样的结构:
struct Base; // not polimorfic
class Derived : public Base; // has pure virtual
class ImplDerived : public Derived // implements pure virtuals
some_function(Base* base);
int main() {
ImplDerived impd;
some_function(&impd);
}
现在,发生了什么:
在桌面Linux 环境中运行:
没有错误。
在some_function
内,基础指针指向& impd 的相同地址。换句话说,在内存中,ImplDerived对象以Base
对象开头。即,当我调试时,我看到了:
ImplDerived : 0xab00
-> Derived : 0xab00
-> Base : 0xab00
在嵌入式设备中运行嵌入式Linux (使用其编译器编译):
错误。
在some_function
内,基础指针再次指向& impd 。
然而,这次它不是 base 的正确位置。因为现在
基础从& impd +4 字节开始。
当我调试时,我看到了:
ImplDerived : 0xab00
-> Derived : 0xab00
-> Base : 0xab04
问题:
AFAIK,基础指针和派生指针之间的偏移量是允许的,正确?
如果是,那么在将指针传递给some_function
找到base
所在的位置时,不应该进行隐式转换吗?
如果应该,那么编译会出现错误吗?
感谢。
编译器:
编辑(结果):
在所有测试之后,我们已经确定这是编译器错误。转换只是不能正常工作,i)非多态基,ii)多重继承。
答案 0 :(得分:3)
不,指向基类和派生类的指针不必匹配。特别是当使用多重继承时会发生这种情况。在你的情况下,原因似乎不同。因为基类不是多态的,所以它没有虚拟表指针作为其隐藏成员。但是,多态派生类开始具有虚拟表指针。我猜你是在编译32位,所以这就是4字节偏移产生的地方:指针是32位。
dynamic_cast
可以解决您的问题。
答案 1 :(得分:0)
AFAIK,基础和派生指针之间的偏移是允许的,对吗?
允许,是的。实际上,如果派生类具有多个(非空)基类,则必须使用它,因为所有基类子对象都不能共享相同的地址。但是,正如您所观察到的那样,即使是唯一的基类子对象也可能不会共享派生对象的地址。
如果是,那么在将指针传递给some_function时,不应该将隐式转换找到基数所在的位置吗?
是。当派生指针被隐式转换为基指针时,它应该指向基础子对象。
如果它应该,那么编译会出错吗?
也许,示例代码应该没问题,但它不完整。