0

假设我有一对基类:

class A
{};

class B
{
    virtual void foo(A* ref);
    virtual void foo2(A* ref);
};

从他们那里,一些派生类:

class C : virtual public A
{
   int data;
};

class D : public B
{
    virtual void foo(A* ref)
    {
        ((C*) (ref)).data = 5;
    }
};

class E : virtual public A
{
    int otherData;
};

class F : public B
{
    virtual void foo2(A* ref)
    {
        ((E*) (ref)).otherData = 6;
    }
};

最后,我们有一个效仿的类,如下所示:

class G : public E, public C
{
};

主要功能如下:

int main()
{
   B* myD = new D();
   B* myF = new F();

   A* myA = new G();

   myD->foo(myA);
   myF->foo2(myA);

   return 0;
}

好的,忽略这是一个“可怕的钻石”的明显事实(由于 ,“多重 As”问题已被避免virtual),一般的想法是我希望我的所有对象都是 Gs、Ds 和 Fs,但是存储为对 As 和 Bs 的引用。我希望能够使用 B(实际上总是 D 或 F)虚函数来修改 G 的值......但是,A 和 B 不知道它们的任何子类,因此不能使用声明他们。这意味着虚函数参数必须始终是指向 A 的指针。但是,D 希望它的输入始终是 C,而 F 希望它的输入始终是 E。虽然如果 G 是,这可能不是问题仅从一个父级继承,我们当前的 G 是从两个父级继承的;我不知道如何this指针实际上在这种情况的基础上下文中工作......但是,我不认为这将是一种可能的情况。

是否有人愿意阐明将指针转换为父/子类的机制,以及是否有任何方法可以实现这一点?

4

3 回答 3

1

假设您已打开 RTTI,您很可能会这样做,您可以使用dynamic_cast尝试将基类指针向上转换为派生(或兄弟)类指针。引用的对象在运行时进行测试以查看它是否是兼容的类,如果这不是有效的向上转换,则它将返回 0,在这种情况下,您可以测试该对象并进行分支。

http://en.wikipedia.org/wiki/Dynamic_cast

于 2012-06-08T07:00:02.940 回答
1

由于A是 的虚拟基础G,因此您不能将A指针G静态转换为指针。的全部含义virtual是“在运行时确定”,因此A您拥有指针的 -subobject 的性质只能在运行时知道。例如,在您的情况下,请考虑:

A * p = new G, q = new C;

现在p和都q指向某个 A子对象,但包含它们的最派生对象的性质仅由实际派生最多的类型决定。因此,不可能有一个单一的、固定的转换规则 from A*toG*或 from A*to C*

执行强制转换的唯一方法是动态的,即通过dynamic_cast<C*>(p)等。

(相比之下,在非虚拟继承中,始终知道子对象与其更多派生对象的关系,因此可以静态转换指针。如果您有多个重复的基,可能会出现命名歧义的问题,但没有问题定位基础子对象。)

于 2012-06-08T07:47:37.607 回答
0

正如 Kerrek 和 Andrew 所说,您应该使用dynamic_cast. 但是,如果 的孩子A是静态的,您可以使用不同的技巧,这可能比dynamic_cast(因为它不依赖于 RTTI,请参阅此问题以获取更多信息)更快。

class C;
class D;
class E;
class F;

class A
{
public:
    virtual C * isC () { return 0; }
    virtual E * isE () { return 0; }
};

class C : virtual public A
{
    friend class D;
    int data;
    C * isC () { return this; }
};

class E : virtual public A
{
    friend class F;
    int otherData;
    E * isE () { return this; }
};

现在,D可以F查询A是否isCisE返回一个有效的指针。

于 2012-06-08T09:41:27.713 回答