类设计并发症(C ++) [英] Class design complication (C++)

查看:151
本文介绍了类设计并发症(C ++)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的课程是


  • 基本

    • Derived_A

    • Derived_B

    • Base
      • Derived_A
      • Derived_B

      • Child_One

      • Child_Two

      • Child_One
      • Child_Two

      Base有两个签名函数:

      Base has two signature functions:

      virtual void foo( const Parent& ) = 0;
      virtual void bar( const Base& ) = 0;
      

      程序的其他部分。

      问题是:

      Derived_A 处理 Child_One Child_Two 相同。但是 Derived_B 对它们的处理方式不同。

      Derived_A treats Child_One and Child_Two the same. But Derived_B treats them differently.

      我应该如何实现?

      一种方法是找出传递给 Derived_B.foo 的对象类型。这显然是设计缺陷。
      我尝试的另一种方法是更改​​签名函数为:

      One way is to find out what kind of object is passed to Derived_B.foo. This would be apparently "a design flaw". The other way I tried is to change the signature functions as:

      class Base
      {
        class Derived_A;
        class Derived_B;
      
      //  virtual void bar( const Base& ) = 0;
        virtual void bar( const Derived_A& ) = 0;
        virtual void bar( const Derived_B& ) = 0;
      }
      
      class Derived_A: public virtual Base
      { 
      
        virtual void foo( const Parent& ) = 0;
      }
      
      class Derived_B: public virtual Base
      { 
        virtual void foo( const Child_A& ) = 0;
        virtual void foo( const Child_B& ) = 0;
      }
      

      但现在 >函数不能使用 Base.foo 。所以我必须写 bar 函数两次,虽然代码是完全一样的。

      But now the bar function cannot use Base.foo. So I have to write the bar function twice, although the code is exactly the same.

      处理问题的方法?你建议哪一个?

      Are there any other ways to deal with the problem? which one do you suggest?

      我想不出一个好的称号。请随时修改它。

      P.S. I couldn't think of a good title. Please feel free to modify it.

      推荐答案

      没有两个类型层次结构之间的关系的详细信息, ,不可能说什么方法是适当的。我对其他答案和另一个可行的替代方法进行了概述,可以扩展到在注释中提到的访问者模式。

      Without details of what the two type hierarchies' relation is with each other and how they interact, it's impossible to say what approach is appropriate. I've composed an overview of the other answers and another viable alternative that can be extended to the visitor pattern which was mentioned in a comment.

      执行多态行为正如Joey Andres所建议的,在 Parent 中实现 virtual 函数的子程序是此问题的典型面向对象解决方案。是否适当取决于对象的责任。

      Performing the polymorphic behaviour in the children implementing a virtual function in Parent as already suggested by Joey Andres is quite typical object oriented solution for this problem in general. Whether it's appropriate, depends on the responsibilities of the objects.

      Olayinka建议的类型检测,在你的问题中已经提到,肯定会闻到kludgy,但是根据细节,是最小的邪恶。它可以用成员函数返回一个枚举(我想这是Olayinka的答案试图表示)或一系列的 dynamic_cast ,如您链接的问题中的答案之一所示。

      The type detection as suggested by Olayinka and already mentioned in your question certainly smells kludgy, but depending on details, can be the minimum of N evils. It can be implemented with member function returning an enum (I guess that's what Olayinka's answer tries to represent) or with a series of dynamic_casts as shown in one of the answers in the question you linked.

      一个简单的解决方案可能是重载中的 foo 基本

      A trivial solution could be to overload foo in Base:

      struct Base {
          virtual void foo(const Parent&) = 0;
          virtual void foo(const Child_Two&) = 0;
      };
      struct Derived_A: Base { 
          void foo(const Parent& p) {
              // treat same
          }
          void foo(const Child_Two& p) {
              foo(static_cast<Parent&>(p));
          }
      };
      struct Derived_A: Base { 
          void foo(const Parent& p) {
              // treat Child_One (and other)
          }
          void foo(const Child_Two& p) {
              // treat Child_Two
          }
      };
      

      如果还有其他子类型 Base $ Child_One Child_Two 同样,然后执行 foo(const Child_Two& / code>可以放在 Base 中以避免重复。

      If there are other subtypes of Base that treat Child_One and Child_Two the same, then the implementation of foo(const Child_Two&) may be put in Base to avoid duplication.

      foo 必须使用适当的静态类型的引用来调用。该调用不会基于动态类型解析。这可能会更好或更糟的你的设计。如果你需要多态行为,你可以使用访问者模式,基本上在上面的解决方案上添加虚拟分派:

      The catch of this approach is that foo must be called with a reference of proper static type. The call will not resolve based on the dynamic type. That may be better or worse for your design. If you need polymorphic behaviour, you can use the visitor pattern which essentially adds virtual dispatch on top of the solution above:

      struct Base {
          foo(Parent& p) {
              p.accept(*this);
          }
          virtual void visit(Child_A&) = 0;
          virtual void visit(Child_B&) = 0;
      };
      
      struct Parent {
          virtual void accept(Base&) = 0;
      };
      
      struct Child_A: Parent {
          void accept(Base& v) {
              v.visit(*this);
          }
      };
      // Child_B similarly
      
      struct Derived_A: Base { 
          void treat_same(Parent&) {
              // ...
          }
          void visit(Child_A& a) {
              treat_same(a);
          }
          void visit(Child_B& b) {
              treat_same(b);
          }
      };
      struct Derived_B: Base { 
          void visit(Child_A&) {
              // ...
          }
          void visit(Child_B&) {
              // ...
          }
      };
      

      有更多的样板,但是因为你似乎很反对在孩子们实现行为,可能是你的好方法。

      There's a bit more boilerplate, but since you seem very averse to implementing the behaviour in the children, this may be good approach for you.

      这篇关于类设计并发症(C ++)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆