C ++多虚拟继承与COM [英] C++ Multiple Virtual Inheritance vs. COM

查看:127
本文介绍了C ++多虚拟继承与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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆