代码之家  ›  专栏  ›  技术社区  ›  Taylor

在不增加耦合的情况下避免动态铸造

c++
  •  -2
  • Taylor  · 技术社区  · 5 年前

    假设我想避免 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);
       }
    }
    

    一种解决方案是向downcast添加一个方法:

    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;
    };
    

    但我们只剩下一个问题:每个问题 类需要添加到 BaseVisitor 导致更多的耦合和更多的重新编译(这是C++,每个修改到 底座 意思是等几分钟)。

    如果我想支持插件,情况会更糟。插件无法修改 底座 基本访问者 ,因此插件无法添加其他 课程。(我意识到典型的C++ RTTI在库之间可能不太好,但是我已经看到了一个定制RTTI系统,显然是QT中的一个。

    我能避开RTTI吗/ 动态铸造 同时保持代码的可扩展性?

    This question 看起来很相似。在我的例子中,我首先愿意使用其他方法来表示我的数据。

    (建议避免 动态铸造 在C++样式指南中,如 this one (第页)

    1 回复  |  直到 5 年前
        1
  •  3
  •   eerorika    5 年前

    HasColor 而其他人不是,那么你必须依靠 dynamic_cast 彩色

    动态铸造 彩色