处理多重继承时如何对齐指针?

| 假设我们有一个具体的类A和一个抽象类B。 考虑一个具体的C,它既继承了A和B,又实现了B:
class C : public A, public B  
{  
/* implementation of B and specific stuff that belongs to C */  
};
现在定义一个签名为“ 1”的函数 这是我的代码,我可以假定指向B的每个指针都是A和B。 在foo \的定义中,如何获得指向A的指针? 一个讨厌但可行的技巧是像这样对齐后指针:
void foo(B* b)  
{  
    A* a = reinterpret_cast<A*>(reinterpret_cast<char*>(b) - sizeof(A));
    // now I can use all the stuff from A  
}
请记住,C没有超类型,实际上,有许多类似于C的类,它们仅是A和B。请随意质疑我的逻辑和本设计示例,但问题仅涉及指针对齐。     
已邀请:
void foo(B* b)  
{  
    //A* a = reinterpret_cast<A*>(reinterpret_cast<char*>(b) - sizeof(A)); // undefined behaviour!!!!
    A* a = dynamic_cast<A*>(b);
    if (a)
    {
       // now I can use all the stuff from A  
    }
    else
    {
       // that was something else, not descended from A
    }
}
忘了说:为了使工作动态转换,A和B都应具有虚拟功能或至少具有虚拟析构函数。否则,没有合法的方法可以进行类型转换。     
拥有大量分别来自set4ѭ和
B
的不相关类的集合是一个非常奇怪的设计。如果存在使
A
B
始终“一起使用”的某些情况,则可以合并它们或引入仅从它们派生而后仅从该类派生的垫片类:
class Shim : A, B {};

class DerivedX : Shim {};
在后一种情况下,您仅使用
static_cast
首先从
A
B
向下转换为
Shim*
,然后使用C ++它将隐式地将
Shim*
指针转换为另一个类。     
如果要在函数中同时使用A类和B类的功能,则应修改该函数以接收C指针:
void foo(C* c);
通常,您认为“每个B同样也是A”是错误的。您可以创建从B接口派生的类,而不是从A类派生的类,这就是为什么编译器在您的特定情况下不会知道“每个B都是A \”的原因。     
扩展Sharptooth的答案(并输入它作为答案,因为我无法在注释中输入格式化的代码),您仍然可以使用填充程序:
class Shim : public virtual A, public virtual B {};
然后:
class Derived1 : public Shim, public virtual A, public virtual B1
{
};

class Derived2 : public Shim, public virtual A, public virtual B2
{
};
B1
B2
实际上必须来自
B
。 但是我怀疑如果您始终需要同时执行
A
B
,您应该同时创建两个接口 继承或合并为一个类;您的
B1
B2
将从那里继承。 (解决方案
dynamic_cast
当然是针对
B
的类别可能也可能不from4ѭ得出。)     

要回复问题请先登录注册