简体   繁体   English

多个继承类引用

[英]Multiple Inheritance Class References

Suppose I have a pair of base classes: 假设我有一对基类:

class A
{};

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

And from them, a few derived classes: 从他们,一些派生类:

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;
    }
};

And finally, we have a class that follows suit, as such: 最后,我们有一个跟随的课程,如下:

class G : public E, public C
{
};

with a main function that goes as follows: 主要功能如下:

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

   A* myA = new G();

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

   return 0;
}

Ok, IGNORING the obvious fact that this is a 'dreaded diamond' (which, the "multiple As" problem has been averted due to virtual ), the general idea is that I want to have all my objects be Gs, Ds and Fs, but stored as references to As and Bs. 好吧,忽略了一个明显的事实,即这是一个“可怕的钻石”(由于virtual而避免了“多重As”问题),一般的想法是我希望我的所有物品都是Gs,Ds和Fs,但存储为As和Bs的引用。 I want to be able to use B's (which is actually always either D or F) virtual functions to modify the values of G... However, A and B do not know of any of their child classes, and thus cannot be declared using them. 我希望能够使用B(实际上总是D或F)虚拟函数来修改G的值...但是,A和B不知道他们的任何子类,因此无法使用他们。 This means that the virtual function arguments must always be a pointer to an A. However, D wants to have it's input always be a C, and F wants it's input to be an E. While this might not have been an issue if G was inheriting from only one parent, our current G is inheriting from 2 parents; 这意味着虚函数参数必须始终是指向A的指针。但是,D希望它的输入始终是C,而F希望它的输入是E.虽然这可能不是问题,如果G是继承自一个父母,我们现在的G继承自2个父母; I do not know how the this pointers actually work in the underlying context of situations like this... however, I do not feel like this is going to be a possible situation. 我不知道this指针实际上是如何在this情况的基础环境中起作用的......但是,我觉得这不会是一种可能的情况。

Would anyone be willing to shed some light on the mechanisms of casting pointers to parent/child classes, and if there would be any way this could be pulled off? 是否有人愿意阐明将指针转换为父/子类的机制,如果有任何方法可以将其删除?

Assuming you have RTTI switched on, which you most likely do, you can use dynamic_cast to attempt to up-cast a base class pointer to a derived (or sibling) class pointer. 假设您已经打开了RTTI(您最有可能这样做),您可以使用dynamic_cast尝试向基类指针上传一个派生(或同级)类指针。 The referenced object is tested at runtime to see if it is a compatible class, if this is not a valid upcast than it will return 0, in which case you can test for that and branch. 引用的对象在运行时进行测试以查看它是否是兼容的类,如果这不是有效的upcast而不是返回0,在这种情况下,您可以测试该分支和分支。

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

Since A is a virtual base of G , you cannot convert a pointer to A to a pointer to G statically. 由于AG的虚拟基础,因此无法将指向A的指针静态转换为指向G的指针。 The whole meaning of virtual is "determined at runtime", and so the nature of the A -subobject to which you have a pointer can only be known at runtime. virtual的整个含义是“在运行时确定的”,因此只有在运行时才能知道有指针的A对象的性质。 For example, in your case consider: 例如,在您的情况下考虑:

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

Now both p and q point to some A -subobject, but the nature of the most-derived object in which they are contained is only determined by the actual most derived type. 现在pq指向某个 A子对象,但是包含它们的最派生对象的性质仅由实际的最大派生类型决定。 Thus it is impossible to have one single, fixed conversion rule from A* to G* or from A* to C* . 因此,不可能有一个单一的固定转换规则,从A*G*或从A*C*

The only way to perform the cast is dynamically, ie via dynamic_cast<C*>(p) etc. 执行dynamic_cast<C*>(p)的唯一方法是动态,即通过dynamic_cast<C*>(p)等。

(By contrast, in non-virtual inheritance it is always known how a subobject relates to its more-derived objects, and thus pointers can be converted statically. There may be issues of naming ambiguity if you have multiple repeated bases, but there's no issue with locating the base subobjects.) (相比之下,在非虚拟继承中,总是知道子对象如何与其更多派生的对象相关,因此指针可以静态转换。如果你有多个重复的基础,可能存在命名歧义的问题,但是没有问题找到基础子对象。)

As Kerrek and Andrew say, you should use dynamic_cast . 正如Kerrek和Andrew所说,你应该使用dynamic_cast However, if the children of A are static, you could use a different trick, which might be faster than dynamic_cast (since it doesn't depend on RTTI, see this question for more information). 但是,如果A的子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; }
};

Now, D and F can query A to see if isC or isE returns a valid pointer. 现在, DF可以查询A以查看isCisE返回有效指针。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM