题
我有一个类实现了2的接口和继承1类。因此,一般看起来是这样的:
class T : public A, public IB, public IC {
};
有一点在代码在哪里我有一个 IB *
, 但真的可以使用一个 A *
.我希望,一个动态的投会是这样的:
IB *b_ptr = new T; // it's really more complicated, but serves the example
A *a_ptr = dynamic_cast<A *>(b_ptr);
不幸的是,这不起作用。是否有一个适当的方式做到这一点?或者我应该实施工作?我已经想过既有 IB
和 IC
继承的几乎从 A
, 但请参考上一次我试过,有一些并发症,即使它不希望的。
任何想法?
编辑:哦,是啊,这是一个插件API,因此不幸的是我没有直接访问 T
类型在这里我需要的 A *
.我已经那么接下来,但如前所述,这是更为复杂。基本上我有2个共用图书馆。 T
和 T1
(在这里我有一个 IB *
)是两个类实现一个插件API和内部的共享图书馆。
为了澄清:这里有一个更具体的例子,我的典型的插件(他们是在单独的图书馆):
插件:
class PluginA : public QObject, public PluginInterface, public OtherInterface {
};
插件B:
class PluginB : public QObject, public PluginInterface {
// in here, I have a PluginInterface *, but really could use a QObject *
// unfortunately, PluginB has absolutely no knowledge of the "PluginA" type
// it just so happens that my PluginInterface * pointer points to an object of type
// PluginA.
};
编辑:我有个猜测的问题是,pluginA和pluginB是在不同的公共图书馆。也许rtti不交叉的模块边界。我想这可能是这种情况,因为人民的例子似乎工作的现在我的测试。具体地说,pluginB没有"所属类别进PluginA"如果我做一个"nm"。这可能是核心的问题。如果是这种情况,我将只需要工作围绕着它无论是通过虚拟继承或一个虚拟的 cast_to_qobject()
能在我的一个接口。
解决方案 4
我终于想通了, 丹尼尔Paull 是正确的,在这一"横向 dybnamic_cast
"应该允许的。我的问题是因为我的代码是涉及公共图书馆。的所属类别从PluginA是不可PluginB.我的解决方案是有效地加 RTLD_NOW
和 RTLD_GLOBAL
我载程序
技术上这是
loader.setLoadHints(QLibrary::ResolveAllSymbolsHint | QLibrary::ExportExternalSymbolsHint);
因为我使用夸脱的插件系统,但同样的差别。这些标志的力量所有的符号从图书馆加载到可以立即解决,可以看到其他图书馆。因此使得所属类别提供给大家,需要它。的 dynamic_cast
工作预计一旦这些标志。
其他提示
每一类至少有一个虚拟的方法?如果不是,那是你的问题。增加一个虚拟析构到每一类应该克服的问题。
以下愉快地作为我说:
class IC
{
public:
virtual ~IC() {}
};
class IB
{
public:
virtual ~IB() {}
};
class A
{
public:
virtual ~A() {}
void foo() { /* stick a breakpoint here to confirm that this is called */ }
};
class T : public A, public IB, public IC
{
public:
virtual ~T() {}
};
int main(void)
{
IB *b_ptr = new T;
A *a_ptr = dynamic_cast<A *>(b_ptr);
a_ptr->foo();
return 0;
}
编辑:
之后所有新的信息,以及不寻常的行为(代码应该只是工作!), 不会的以下帮助吗?我已经介绍了一个接口,称为IObject和使用虚拟的继承,确保只有一个副本的这个基类。你可以现在投向IObject然后到一个?
class IObject
{
public:
virtual ~IObject() {}
};
class IC : virtual public IObject
{
public:
virtual ~IC() {}
};
class IB : virtual public IObject
{
public:
virtual ~IB() {}
};
class A : virtual public IObject
{
public:
virtual ~A() {}
void foo() { /* stick a breakpoint here to confirm that this is called */ }
};
class T : virtual public A, virtual public IB, virtual public IC
{
public:
virtual ~T() {}
};
int main()
{
IB *b_ptr = new T;
A *a_ptr = dynamic_cast<A *>( dynamic_cast<IObject *>(b_ptr) );
a_ptr->foo();
return 0;
}
我不认为这是正确的解决方案,但它可能会提供一些信息为什么...
是否有一个适当的方式做到这一点?或者我应该实施工作?我已经想过既具有IB和IC继承的几乎从一,但是请参考上一次我试过,有一些并发症,即使它不希望的。
我把它然后,这些定义的IB和IC是在你的控制之下。
还有的方式在其COM接口工作窗口;这些做什么,你是想要做的事,即:
- 从一个到另一个接口
- 执行是不透明的到来电
- 只有实施知道其它实现接口
不这样做,你可以做这样的事情(未经测试的代码之前)...
interface IQueryInterface
{
IQueryInterface* queryInterface(const Guid* interfaceId);
};
interface IB : public abstract IQueryInterface
{
...
};
interface IC : public abstract IQueryInterface
{
...
};
//within your implementation class
IQueryInterface* T::queryInterface(const Guid* interfaceId)
{
if (matches(interfaceId,GUID_IB))
return (IB*)this;
if (matches(interfaceId,GUID_IC))
return (IC*)this;
if (matches(interfaceId,GUID_A))
return (A*)this;
return 0;
}
一个更简单、更硬编码版本,这将是:
class A; //forward reference
interface IB
{
virtual A* castToA() { return 0; }
};
class T : public A, IB, IC
{
virtual A* castToA() { return this; }
};
投到一个T*第一然后到:
IB *b_ptr = new T; // it's really more complicated, but serves the example
A *a_ptr = dynamic_cast<T *>(b_ptr);
如果IB一般应该料到,那么也许IB应该继承A.
编辑:我只是想这个和它的工作-注意,E是未知的时间编写的主要方法。
struct A
{
virtual ~A() {}
};
struct C
{
virtual ~C() {}
};
A* GetA();
int main()
{
C *y = dynamic_cast<C *>(GetA());
if (y == NULL)
cout << "Fail!";
else
cout << "Ok!";
}
struct E : public A, public C
{
};
A* GetA() { return new E(); }
我最近也被打扰,同样的问题。更多信息,请参见海湾合作委员会的常见条目:
http://gcc.gnu.org/faq.html#dso
除了指示dlopen里与RTLD_*旗,一些身的这个问题可以解决的链接,以及,看看它-E-Bsymbolic的选择。