将类强制转换为类

Casting a class to a class

本文关键字:转换      更新时间:2023-10-16

[这里嵌入的C人,被嵌入的C++所困扰]

有一个类派生自另一个类,如下所示:

class DerivedThing: public BaseThing {
...
}

有一些代码,我无法控制,它接收指向DerivedThing的指针,并最终将该指针转换为BaseThing。 我被引导相信这是有效的。 无论如何,我需要实现我自己的DerivedThing但它需要子类化一些其他的东西:

class MyDerivedThing: public BaseThing, public AnotherThing {
...
}

我需要做什么来确保演员阵容仍然有效? 我问是因为在我的情况下,肯定调用了错误的函数。

编辑:我无法控制的代码中的转换是:

int setInterface(void* context)
{
interface[0] = (BaseThing *) context;
...

我在评论时过于悲观!

投射以BaseThing*自己,并将其传递给接受void*的函数,应该可以工作。

仅按原样传递派生对象的地址的问题在于其地址被隐式转换为void*。因此,有关其类型和所涉及的类层次结构的所有信息都将丢失。

然后,接收函数假定现在void*指针直接指向BaseThing。这就是事情开始循环的地方,表现为诸如调用错误函数之类的症状 -如果你幸运的话- 因为假设派生对象和任何特定的基子对象具有相同的地址并不是(总是/可靠地)一个有效的假设,其中多重和/或虚拟继承在起作用。

中场休息:目前还不清楚为什么这个引用的基地顺序会导致问题:

class MyDerivedThing: public BaseThing, public AnotherThing {

。但是有各种可能性。例如,如果这里的所有三个类都没有虚拟方法,那么应该没有问题。但是,例如,如果BaseThing不是虚拟的,但其他两个是虚拟的,编译器可能会在对象的顶部放置一个虚拟表指针,这将炸毁任何只接受该地址并假设那里有BaseThing的东西。

无论如何 - 通过在传递之前强制转换自己,编译器可以执行适当的类型感知转换,执行可能需要的任何调整算术,到对象中BaseThing的地址 - 然后将其传递给函数。它仍然经过转换到void*和返回,但现在保证最终代表BaseThing的地址。

我仍然会质疑作者为什么这个函数需要void*.关于C++的关键因素之一是类型安全。void*嘲弄了这一点。更糟糕的是,他们只是立即将上述void*投给了BaseThing*。那么,为什么不直接...首先要BaseThing*?然后,编译器可以在任何调用站点隐式执行上述安全类型转换,而不是让您这样做。