避免使用Dynamic_cast而不增加耦合

avoiding dynamic_cast without increasing coupling

本文关键字:增加 耦合 cast Dynamic      更新时间:2023-10-16

假设我想在以下代码中避免dynamic_cast

struct Base { ... stuff ... };
struct HasColor {
  virtual Color getColor() const = 0;
  virtual void setColor(Color) = 0;
};
struct Foo : public Base, public HasColor {
  ... implements HasColor methods
};
...
vector<Base*> collection;
...
for(auto element : collection) {
   if(auto hasColor = dynamic_cast<HasColor*>(element)) {
      hasColor->SetColor(myColor);
   }
}

一种解决方案是添加一种方法以降低:

struct Base {
  HasColor* toHasColor() { return nullptr; }
};
struct Foo : public Base, public HasColor {
  ...
  HasColor* toHasColor() { return this; }
};

这意味着Base需要了解每个Has接口,增加耦合。

让我们尝试访客模式:

struct BaseVisitor {
   void visitHasColor(HasColor& hasColor) = 0
};
struct Base {
   virtual void visit(BaseVisitor& visitor) = 0;
};

但是我们遇到了相同的问题:每个Has类都需要添加到BaseVisitor中,导致更多的耦合并进行更多的重新编译(这是C ,每个对Base的修改意味着等待几分钟(。

( (。

如果我想支持插件,情况会变得更糟。插件无法修改BaseBaseVisitor,因此插件无法添加其他Has类。(我意识到典型的C RTTI在库之间可能无法正常工作,但是我看到了一个自定义的RTTI系统,显然是QT中的一个。(

我可以在保持代码扩展时避免RTTI/dynamic_cast吗?

这个问题似乎相似。就我而言,我首先对代表我的数据表示愿意。

(建议避免使用C 样式指南中的dynamic_cast。(

如果您有各种各样的集合,有些是 HasColor,而另一些则不是,那么您必须依靠 dynamic_cast或类似的rtti才能将对象用作 HasColor或者,您必须使用访问者模式将依赖关系倒置,这引入了您的问题。

不需要使用dynamic_cast或其他RTTI的解决方案是仅使用HasColor实例的集合。