[嵌入式C人员,嵌入式C ++难以置信]
有一个派生自另一个的课程,如下所示:
class DerivedThing: public BaseThing {
...
}
有一些我无法控制的代码,它接收指向DerivedThing
的指针,并最终强制转换指向BaseThing
的指针。我认为这很有效。无论如何,我需要实现我自己的DerivedThing
,但它需要继承其他一些东西:
class MyDerivedThing: public BaseThing, public AnotherThing {
...
}
我需要做些什么来确保演员阵容仍然有效?我问,因为在我的情况下,错误的功能肯定是被调用的。
编辑:我无法控制的代码中的强制转换是:
int setInterface(void* context)
{
interface[0] = (BaseThing *) context;
...
答案 0 :(得分:3)
评论时我过于悲观了!
自己投射到BaseThing*
并将 传递给使用void*
的函数,应该可以正常工作。
按原样传递派生对象的地址的问题是它的地址被隐式转换为void*
。因此,有关其类型和所涉及的类层次结构的所有信息都将丢失。
然后接收函数假定now - void*
指针直接指向BaseThing
。这就是事情开始变得循环的过程,表现为被称为错误函数的症状 - 如果你很幸运 - 因为假设派生对象和任何特定的基础子对象具有相同的地址是不是(总是/可靠地)一个有效的假设,其中有多个和/或虚拟继承在起作用。
中场休息:目前还不清楚为什么这种引用顺序的基地会引起问题:
class MyDerivedThing: public BaseThing, public AnotherThing {
......但是有各种各样的可能性。例如,如果这里的所有三个类都没有虚拟方法,那么就不应该有问题。但是,例如,如果BaseThing
不是虚拟的,而是其他两个中的任何一个,则编译器可能会在对象的顶部放置一个虚拟表指针,这会炸掉任何只占用该地址的内容并假设#39; sa BaseThing
那里。
无论如何 - 通过在传递之前自己投射,编译器可以执行适当的类型感知强制转换,执行可能需要的任何调整算法,到对象中BaseThing
的地址 - 然后将其传递给功能。它仍然会转换为void*
并返回,但现在可以保证最终代表BaseThing
的地址。
我仍然质疑作者为什么这个函数需要void*
。关于C ++的关键之一是类型安全。 void*
对此嗤之以鼻。更糟糕的是,无论如何,他们只是立即将void*
投射到BaseThing*
。那么,为什么不......首先考虑BaseThing*
?然后编译器可以隐式地在任何调用站点执行上面提到的安全类型转换,而不是让你这样做。