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

查看:18
本文介绍了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.

我想我会试试这个地方玩.事实证明,使用 Flash 播放器 10 版的以下声明会使您的应用崩溃.

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"指针值.但是删除虚拟"就可以了!没有崩溃,同样的this"指针.

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.

干杯亚当

推荐答案

第一个示例中的虚拟继承没有做任何事情.我敢打赌,如果它们被删除,它们会编译成相同的代码.

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.

虚拟继承的类只是标记编译器,它应该合并以后版本的 Der1Der2.由于每一个都只出现在继承树中,因此没有做任何事情.虚拟对象对 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))

虚拟继承仅影响下一个继承的类,并且仅适用于已被定义为虚拟的实例.这与您的预期相反,但它是对类编译方式的限制.

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

必须在 C 和 B 中将 A 标记为 virtual 而不是 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天全站免登陆