处理多重继承时如何对齐指针?
假设我们有一个具体的类 A 和一个抽象类 B。
考虑一个具体的 C,它继承自 A 和 B,并实现 B:
class C : public A, public B
{
/* implementation of B and specific stuff that belongs to C */
};
现在我定义一个函数,其签名为 void foo(B* b);
这是我的代码,我可以假设每个指向 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。请随意质疑我的逻辑和这个设计示例也是如此,但问题仅涉及指针对齐。
Say we have a concrete class A, and an abstract class B.
Consider a concrete C, that inherits from both A and B, and implements B:
class C : public A, public B
{
/* implementation of B and specific stuff that belongs to C */
};
Now I define a function which signature is void foo(B* b);
This is my code, I can assume that every pointers to B are both A and B.
In foo's definition, how to get a pointer to A?
A nasty but working trick is to align back pointers like so:
void foo(B* b)
{
A* a = reinterpret_cast<A*>(reinterpret_cast<char*>(b) - sizeof(A));
// now I can use all the stuff from A
}
Keep in mind that C does not have a super type and actually, there are many classes akin to C which only are A and B. Feel free to question both my logic and this sample of design as well but the question is only concerning pointers alignment.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
忘了说:为了使工作动态转换,A 和 B 都应该有虚拟函数或至少有虚拟析构函数。否则就没有合法的方法来进行类型转换。
Forgot to say: in order to make work dynamic cast both A and B should have virtual function(s) or at least virtual destructors. Otherwise there is no legal way to do that type conversion.
拥有大量从
A
和B
派生的不相关的类是一个非常奇怪的设计。如果有什么东西使A
和B
始终“一起使用”,您可以合并它们或引入一个填充类 em> 仅从它们派生,然后仅从该类派生:在后一种情况下,您只需使用
static_cast
首先从A
或B
向下转换code> 到 Shim*,然后 C++ 会隐式地将Shim*
指针转换为另一个类。Having a huge set of unrelated classes that both derive from
A
andB
is a very strange design. If there's something that makesA
andB
always be "used together" you could either merge them or introduce a shim class that only derives from them and then only derive from that class:and in the latter case you just use
static_cast
to first downcast fromA
orB
toShim*
and then C++ it will implicitly convert theShim*
pointer to the other class.如果您想在函数中使用 A 类和 B 类的功能,那么您应该修改该函数以接收 C 指针:
一般来说,您认为“每个 B 也是 A”的假设是错误的。您可以创建从 B 接口派生的类,而不是从 A 类派生的类,这就是为什么编译器不会知道在您的特定情况下“每个 B 都是 A”。
If you want to use the functionality of both class A and Class B in your function then you should modify the function to receive C pointers:
And in general you are wrong with you assumption that "every B is an A as well". You could create classes derived from you B interface and not derived from Class A, that's why the compiler won't know that in your specific case "every B is an A".
扩展 Sharptooth 的答案(并将其作为答案输入,因为我无法将格式化代码放入注释中),您仍然可以使用垫片:
然后:
B1
和B2
必须实际上从B
派生。但我怀疑如果你总是需要同时实现
A
和B
,您应该创建一个包含两者的界面,或者通过继承或将两者合并为一个类;您的
B1
和B2
将从中继承。 (解决方案与dynamic_cast
当然,是针对派生的情况B
的类可能也可能不是从A
派生的。)Expanding on sharptooth's answer (and entering it as an answer, because I can't get formatted code into a comment), you can still use the shim:
Then:
B1
andB2
must derive virtually fromB
.But I suspect that if you always need to implement both
A
andB
, you should create a single interface with both, either byinheriting, or coalising both into a single class; your
B1
andB2
would inherit from that. (The solution withdynamic_cast
, of course, is for the case where the derivedclass of
B
may or may not also derived fromA
.)