在C ++中应该派生类指针指向基类指针吗?

时间:2016-02-01 09:52:53

标签: c++ stack

我非常罕见的错误,并了解我需要了解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所在的位置时,不应该进行隐式转换吗?

  • 如果应该,那么编译会出现错误吗?

感谢。

编译器:

  • 桌面:gcc 4.9.2-10 Debian 64位
  • Embedded:gcc 4.8.0

编辑(结果):

在所有测试之后,我们已经确定这是编译器错误。转换只是不能正常工作,i)非多态基,ii)多重继承。

2 个答案:

答案 0 :(得分:3)

不,指向基类和派生类的指针不必匹配。特别是当使用多重继承时会发生这种情况。在你的情况下,原因似乎不同。因为基类不是多态的,所以它没有虚拟表指针作为其隐藏成员。但是,多态派生类开始具有虚拟表指针。我猜你是在编译32位,所以这就是4字节偏移产生的地方:指针是32位。

dynamic_cast可以解决您的问题。

答案 1 :(得分:0)

  

AFAIK,基础和派生指针之间的偏移是允许的,对吗?

允许,是的。实际上,如果派生类具有多个(非空)基类,则必须使用它,因为所有基类子对象都不能共享相同的地址。但是,正如您所观察到的那样,即使是唯一的基类子对象也可能不会共享派生对象的地址。

  

如果是,那么在将指针传递给some_function时,不应该将隐式转换找到基数所在的位置吗?

是。当派生指针被隐式转换为基指针时,它应该指向基础子对象。

  

如果它应该,那么编译会出错吗?

也许,示例代码应该没问题,但它不完整。