该应用程序定义了 3 个要在插件中实现的接口(interface)。 Widget
始终是基础。
// Application code...
class Widget {
virtual void animate() = 0;
};
class BigWidget : public Widget {
};
class SmallWidget : public Widget {
};
每个接口(interface)的实现都源自NiceWidget
,它提供了一些插件内部通用信息。
// Plug-in code...
class NiceWidget {
// nice::Thing is only known in plug-in code.
nice::Thing thing();
};
class NiceBigWidget : public NiceWidget, public BigWidget {
void animate() override;
};
class NiceSmallWidget : public NiceWidget, public SmallWidget {
void animate() override;
};
func
从应用程序代码中调用。 wid
已知是由该插件实现的。因此 wid 也是一个 NiceWidget
。 func
的目标是调用它的 thing
方法。
// Plugin-in code...
void func(Widget* wid) {
// wid is either NiceBigWidget or NiceSmallWidget.
auto castedBig = dynamic_cast<NiceBigWidget*>(wid);
if (castedBig) {
castedBig->thing().foo();
return;
}
auto castedSmall = dynamic_cast<NiceSmallWidget*>(wid);
if (castedSmall) {
castedSmall->thing().foo();
return;
}
assert(false);
}
但是,随着层次结构大小的增加,尝试将 wid
转换为每个 Nice*
可能会变得非常糟糕。有更好的解决方案吗?
最佳答案
首先:如果您知道 wid
始终是 NiceWidget*
,为什么不在 func()
中这么说呢?而且你根本不需要类型转换:
void func(NiceWidget* wid)
{
wid->thing().foo(); // Done
}
即使您出于某种原因无法更改函数签名,您也只需要一次强制转换:
void func(Widget* wid)
{
NiceWidget* casted = dynamic_cast<NiceWidget*>(wid);
if (casted)
casted->thing().foo();
else
throw std::exception(); // Well, throw the right exception
}
当然,如果您认为这更适合您的目的,您可以 assert()
而不是抛出异常。
无论如何,您只需要一个指向定义需要使用的函数的类(在本例中为 thing()
)的指针,而不是指向最派生类的指针。如果您要重写派生类中的函数,请将其设为虚拟,这样就完成了。
关于c++ - 插件代码中的公共(public)基类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14143002/