C ++单继承的内存布局是否与此C代码相同?

问题描述 投票:1回答:2

我正在使用一个用C语言编写的库,它继承如下:

struct Base
{
   int exampleData;
   int (function1)(struct Base* param1, int param2);
   void (function2)(struct Base* param1, float param2);
   //...
};

struct Derived
{
   struct Base super;
   //other data...
};

struct Derived* GetNewDerived(/*params*/)
{
    struct Derived* newDerived = malloc(sizeof struct Derived);
    newDerived->super.function1 = /*assign function*/;
    newDerived->super.function2 = /*assign function*/;
    //...
    return newDerived;
}

int main()
{
    struct Derived *newDerieved = GetNewDerived(/*params*/);
    FunctionExpectingBase((struct Base*) newDerived);
    free(newDerived);
}

我理解这是有效的,因为指向Derived的指针与指向Derived的第一个成员的指针相同,因此转换指针类型足以将对象视为其“基类”。我可以编写任何分配给function1function2的内容,以便将来自Base*的传入指针转换为Derived*来访问新数据。

我正在扩展这样的代码功能,但我使用的是C ++编译器。我想知道以下是否与上述相同。

class MyDerived : public Base
{
    int mydata1;
    //...

public:
    MyDerived(/*params*/)
    {
        function1 = /*assign function pointer*/;
        function2 = /*assign function pointer*/;
        //...
    }

    //...
};

int main()
{
    MyDerived *newDerived = new MyDerived(/*params*/);
    FunctionExpectingBase( static_cast<Base*>(newDerived) );
    delete newDerived;
}

我可以期望编译器以相同的方式在MyDerived中布局内存,这样我可以执行相同的指针转换以将我的对象传递给他们的代码吗?或者我必须继续写它更像他们的C架构,而不是利用C ++编译器为我做一些更乏味的工作?

我只考虑单一继承这个问题的范围。

c++ c pointers inheritance
2个回答
3
投票

根据Adding a default constructor to a base class changes sizeof() a derived typeWhen extending a padded struct, why can't extra fields be placed in the tail padding?内存布局可以改变,即使你只是添加构造函数到MyDerived或任何其他方式使其非POD。所以我担心没有这样的保证。实际上,您可以使用正确的编译时断言来验证两种结构的相同内存布局,但这种解决方案似乎并不安全并且不受标准C ++的支持。

另一方面,为什么你的C ++包装器MyDerived不能继承Derived?这将是安全的(因为当Derived被投放到Base并返回时它可以是安全的,但我认为这是你无法控制的)。它可能会将MyDerived::MyDerived()中的初始化代码更改为更详细,但我认为这是适当解决方案的小价格。


0
投票

对于你的问题它并不重要,因为“客户端”代码只关心有一个有效的Base*指针:他们不会在Derived或其他任何东西中转发它,或者复制它。

© www.soinside.com 2019 - 2024. All rights reserved.