C ++多虚拟继承与COM [英] C++ Multiple Virtual Inheritance vs. COM
问题描述
网络中出现了可怕的钻石问题的解释。
所以是StackOverflow。我认为我理解这一点,但我不能把这些知识翻译成类似但不同的东西。
The net is overflowing with explanations of the "dreaded diamond problem". So is StackOverflow. I think I understand that bit, but I fail to translate that knowledge into comprehending something similar yet different.
我的问题开始于纯C ++问题,但答案可能很好分支到MS-COM细节。一般的问题是:
My question begins as a pure C++ question, but the answer might well branch over into MS-COM specifics. The general problem question goes:
class Base { /* pure virtual stuff */ };
class Der1 : Base /* Non-virtual! */ { /* pure virtual stuff */ };
class Der2 : Base /* Non-virtual! */ { /* pure virtual stuff */ };
class Join : virtual Der1, virtual Der2 { /* implementation stuff */ };
class Join2 : Join { /* more implementation stuff + overides */ };
这是不是 虚拟在这里做什么?
This is not the classic diamond solution. Exactly what does "virtual" do here?
我真正的问题是试图理解一个在我们的朋友的地方在CodeProject的讨论。它涉及一个自定义类为Flash创建一个透明容器
My real problem is trying to understand a discussion over at our friends' place at CodeProject. It involves a custom class for creating a transparent container for the Flash player.
我以为我会尝试这个地方的乐趣。事实证明,以下声明导致您的应用程序崩溃,版本为10的Flash播放器。
I thought I would try this place for fun. It turns out that the following declaration crashes your app, with version 10 of the Flash player.
class FlashContainerWnd: virtual public IOleClientSite,
virtual public IOleInPlaceSiteWindowless,
virtual public IOleInPlaceFrame,
virtual public IStorage
调试显示,当输入函数实现(QueryInterface等)时,从不同的调用者,我得到不同的this-pointer值为不同的调用。
但是删除虚拟即可。没有崩溃,也没有崩溃。
Debugging shows that when entering the function implementations (QueryInterface etc), from different callers, I get different "this"-pointer values for different calls. But removing "virtual" does the trick! No crashes, and same "this"-pointer.
清楚地了解到底发生了什么。非常感谢。
I would like to clearly understand exactly what is going on. Thanks a lot.
干杯
Adam
Cheers Adam
推荐答案
第一个例子中的虚拟继承不做任何事情。
The virtual inheritance in the first example don't do anything. I would wager that they compile to the same code if they were removed.
虚拟继承的类只是标记编译器应该合并更新版本的 Der1
或 Der2
。由于只有一个出现在继承树中,所以没有做任何事情。虚拟对 Base
没有影响。
The virtually inherited class just flag the compiler that it should merge later versions of Der1
or Der2
. Since only one of each appears in the inheritance tree nothing is done. The virtuals have no effect on Base
.
auto p = new Join2;
static_cast<Base*>(static_cast<Der1*>(p)) !=
static_cast<Base*>(static_cast<Der2*>(p))
虚拟继承仅影响下一个继承的类,并且只对已被delcared的实例有效。这是从你期望的后退,但它是对类编译方式的限制。
The virtual inheritance only effects the next inherited class, and only for instances that have been delcared virtual. This is backward from what you would expect, but it's a limitation on the way classes are compiled.
class A {};
class B : virtual public A {};
class C : virtual public A {};
class D : public A {};
class E : virtual public A, public B, public C, public D {};
class F : public A, public B, public C, public D {};
F::A != F::B::A or F::C::A or F::D::A
F::B::A == F::C::A
F::D::A != F::B::A or F::C::A or F::A
E::B::A == E::C::A == E::A
E::D::A != E::B::A or E::C::A or E::D::A
原因之一A必须在C和B E或F是C和B需要知道不调用A的构造函数。通常他们会初始化他们的副本。当他们参与钻石遗传时,他们不会。但你不能重新编译B和C不构造A.这意味着C和B必须提前知道创建构造函数代码,其中A的构造函数不被调用。
One of the reasons A must be marked virtual in C and B instead of E or F is that C and B need to know not to call A's constructor. Normally they would have initialize each of their copies. When they are involved in diamond inheritance they wont. But you cant recompile B and C to not construct A. That means C and B have to know ahead of time to create constructor code where A's constructor is not called.
这篇关于C ++多虚拟继承与COM的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!