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

如何处理类及其属性的抽象和专门化?

  •  1
  • Delgan  · 技术社区  · 7 年前

    摘要 标题

    更清楚地说:

    • 我有两节课 Controler Interface (硬件感知,与设计模式无关)
    • 这两种方法都是抽象的,带有一些纯虚方法,因此都是子类化的
    • 我每个都需要 控制器 创建为与 对象
    • 每个 控制器 子类只处理 子类( ControlerA + InterfaceA ControlerB + InterfaceB 但不是 ControlerA + InterfaceB )
    • 接口 子类有自己的方法没有继承(这就是为什么只有一种 控制器 (我可以使用它)
    • 这个 控制器 基类需要调用基类的某些方法

    我试着通过考试 接口 构造函数,因此在我的类定义中 属性表示抽象基类。但是如果我的 控制器 接口 A、 出现编译错误,原因是 接口 基类不拥有此方法。

    我找到的唯一解决办法就是打电话 dynamic_cast ,但这显然是错误的。


    接口 课程:

    class Interface {
    public:
      Interface() {};
      virtual void method() = 0;
    };
    
    class InterfaceA : public Interface {
    public:
      InterfaceA() : Interface() {};
      void method() override { cout << "A overriding" << endl; }
      void onlyA() { cout << "A only" << endl; }
    };
    
    class InterfaceB : public Interface {
    public:
      InterfaceB() : Interface() {};
      void method() override { cout << "B overriding" << endl; }
      void onlyB() { cout << "B only" << endl; }
    };
    

    控制器 课程:

    class Controler {
    public:
      Controler(Interface* i) : m_interface(i) {};
      virtual void uniqueMethod() = 0;
      void commonMethod() { m_interface->method(); }
      Interface* m_interface;
    };
    
    class ControlerA : public Controler {
    public:
      ControlerA(InterfaceA* i) : Controler(i) {};
      void uniqueMethod() override {dynamic_cast<InterfaceA *>(m_interface)->onlyA();}
    };
    
    class ControlerB : public Controler {
    public:
      ControlerB(InterfaceB* i) : Controler(i) {};
      void uniqueMethod() override {dynamic_cast<InterfaceB *>(m_interface)->onlyB();}
    };
    

    下面是我计划如何使用它们:

    auto ia = new InterfaceA();
    auto ca = ControlerA(ia);
    ca.commonMethod();  // Method defined in the base class
    ca.uniqueMethod();  // Method defined in InterfaceA only
    

    你可以试穿一下 Repl.it .

    有什么设计模式可以解决这个问题吗?

    1 回复  |  直到 7 年前
        1
  •  2
  •   Oliv    7 年前

    m_interface 以及实现的对象的动态类型 Controler 控制器 班级。所以 会员卡位置不正确。

    结果是,您需要在运行时使用 dynamic_cast uniqueMethod . 如果不变量被破坏,代码将具有UB,因为它将取消对空指针的引用。

    因此,这实际上不是一个设计模式问题,而是一个更基本的面向对象编程建议: 类必须确保不变量。

    class Controler {
    public:
      virtual void uniqueMethod() = 0;
      virtual void commonMethod() = 0;
    };
    
    class ControlerA : public Controler {
    public:
      ControlerA(InterfaceA* i):m_interface{i} {
        assert(dynamic_cast<InterfaceA*>(i)!=nullptr);
        };
      void uniqueMethod() override { m_interface->onlyA();}
      void commonMethod() override { m_interface->method(); }
    private: InterfaceA* m_interface;
    };
    
    class ControlerB : public Controler {
    public:
      ControlerB(InterfaceB* i):m_interface{i} {
        assert(dynamic_cast<InterfaceB*>(i)!=nullptr);
        };
      void uniqueMethod() override { m_interface->onlyB();}
      void commonMethod() override { m_interface->method(); }
    private: InterfaceB* m_interface;
    };
    

    现在,我们有了一个规则模式,我们可以在这里考虑更通用的设计:

    template<class Inter,void(Inter::* OnlyFunc)()>
    class ControlerImpl : public Controler {
    public:
      ControlerImpl(Inter* i):m_interface{i} {
        assert(dynamic_cast<Inter*>(i)!=nullptr);
        };
      void uniqueMethod() override { (m_interface->*OnlyFunc)();}
      void commonMethod() override { m_interface->method(); }
      private: Inter* m_interface;
    };
    using ControlerA = ControlerImpl<InterfaceA,&InterfaceA::onlyA>;
    using ControlerB = ControlerImpl<InterfaceB,&InterfaceB::onlyB>;