C++;如何替换此if…else语句? 我有以下C++代码(简化版): 类形状 { bool isCircle=false; bool-isSquare=false; } 班级圈子:公共形态 { //一些特别成员/方法 } 阶级广场:公共形态 { //一些特别成员/方法 } 类CAD { 虚拟绘制圆(圆*圆)=0; } SWX类:公共CAD { 虚拟画圈(Circle*Circle){//在SWX系统上做一些画圈的事情} } class PRO:公共CAD { 虚拟画圈(Circle*Circle){//在PRO系统上做一些画圈的事情} } int main() { 圆圈*圆圈=新圆圈(); 圆->isCircle=true; Square*sq=新广场; sq->isSquare=true; 矢量形状; 形状。推回(圆形); 形状。推回(sq); SWX*SWX=新的SWX(); 对于(int i=0;iisCircle) { SWX->DrawCircle((圆*)(形状[i]); } else if(形状[i]->isSquare) { SWX->DrawSquare((正方形*)(形状[i]); } }

C++;如何替换此if…else语句? 我有以下C++代码(简化版): 类形状 { bool isCircle=false; bool-isSquare=false; } 班级圈子:公共形态 { //一些特别成员/方法 } 阶级广场:公共形态 { //一些特别成员/方法 } 类CAD { 虚拟绘制圆(圆*圆)=0; } SWX类:公共CAD { 虚拟画圈(Circle*Circle){//在SWX系统上做一些画圈的事情} } class PRO:公共CAD { 虚拟画圈(Circle*Circle){//在PRO系统上做一些画圈的事情} } int main() { 圆圈*圆圈=新圆圈(); 圆->isCircle=true; Square*sq=新广场; sq->isSquare=true; 矢量形状; 形状。推回(圆形); 形状。推回(sq); SWX*SWX=新的SWX(); 对于(int i=0;iisCircle) { SWX->DrawCircle((圆*)(形状[i]); } else if(形状[i]->isSquare) { SWX->DrawSquare((正方形*)(形状[i]); } },c++,polymorphism,C++,Polymorphism,我希望不再需要if…else(如果在下文所述的限制范围内可能的话) 我现在的限制是: CAD和派生类是具有各种外部依赖关系的大型类 CAD类不能与形状类和派生类合并(这很理想,因为我可以使用多态性来解决我的问题),因为其他项目/类依赖于形状类,而不能依赖于CAD类 有十几个形状派生类和六个CAD派生类,如果……其他派生类在许多地方发生,那么这将有助于任何简单易懂的解决方案(更容易说服我的队友更改遗留代码) 欢迎您提供任何建议/意见/解决方案。此问题的标准解决方案,特别是考虑到您对依赖关系的限

我希望不再需要if…else(如果在下文所述的限制范围内可能的话)

我现在的限制是:

  • CAD和派生类是具有各种外部依赖关系的大型类
  • CAD类不能与形状类和派生类合并(这很理想,因为我可以使用多态性来解决我的问题),因为其他项目/类依赖于形状类,而不能依赖于CAD类
  • 有十几个形状派生类和六个CAD派生类,如果……其他派生类在许多地方发生,那么这将有助于任何简单易懂的解决方案(更容易说服我的队友更改遗留代码)

欢迎您提供任何建议/意见/解决方案。

此问题的标准解决方案,特别是考虑到您对依赖关系的限制,是使用

以下是访客模式在您的案例中的工作方式:

  • 您需要一个抽象的
    ShapeVisitor
    类。它对每个具体的Shape子类都有一个抽象的
    Visit
    方法。例如:
    Visit(圆圈*)
    Visit(正方形*)
    ,等等
  • Shape有一个抽象的
    AcceptVisitor(ShapeVisitor*)
    方法
  • 每个形状子类实现的
    AcceptVisitor
    就像调用
    visitor->Visit(this)
  • 每个
    CAD
    类都是一个
    ShapeVisitor
    Visit
    方法为特定类型的
    Shape
    绘制适当的图形。无需条件或铸造
下面是代码的一个修改版本,它以一种非常低影响的方式使用访问者模式:

class Circle;
class Square;
class ShapeVisitor
{
    virtual void Visit(Circle *circle) = 0;
    virtual void Visit(Square *square) = 0;
}

class Shape
{
    virtual void AcceptVisitor(ShapeVisitor *visitor) = 0;
}


class Circle : public Shape
{
    // some special members/methods

    virtual void AcceptVisitor(ShapeVisitor *visitor)
    {
        visitor->Visit(this);
    }
}

class Square : public Shape
{
    // some special members/methods

    virtual void AcceptVisitor(ShapeVisitor *visitor)
    {
        visitor->Visit(this);
    }
}

class CAD : public ShapeVisitor
{
    virtual DrawCircle(Circle *circle) = 0;
    virtual DrawSquare(Square *square) = 0;

    virtual void Visit(Circle *circle) {
        DrawCircle(circle);
    }

    virtual void Visit(Square *square) {
        DrawSquare(square);
    }
}

class SWX : public CAD
{
    virtual DrawCircle(Circle *circle){// do some stuff that draws circle on SWX system}

}

class PRO : public CAD
{
    virtual DrawCircle(Circle * circle){// do some stuff that draws circle on PRO system}
}

int main()
{
    Circle * circle = new Circle();
    Square * sq = new Square;

    vector<Shape*> shapes;
    shapes.push_back(circle);
    shapes.push_back(sq);

    SWX * swx = new SWX();

    for( int i = 0 ; i < shapes.size() ; ++i )
    {
        shapes[i]->AcceptVisitor(SWX);
    }
}
类圈;
班级广场;
类形位器
{
虚拟无效访问(圆圈*圆圈)=0;
虚拟无效访问(平方*平方)=0;
}
阶级形态
{
虚空接受访问者(ShapeVisitor*visitor)=0;
}
班级圈子:公共形态
{
//一些特别成员/方法
虚拟空接受访问者(ShapeVisitor*访问者)
{
访客->访问(本);
}
}
阶级广场:公共形态
{
//一些特别成员/方法
虚拟空接受访问者(ShapeVisitor*访问者)
{
访客->访问(本);
}
}
CAD类:公共形状显示器
{
虚拟绘制圆(圆*圆)=0;
虚拟DrawSquare(Square*Square)=0;
虚拟无效访问(圆圈*圆圈){
画圈(圈);
}
虚拟虚空访问(Square*Square){
广场(广场);
}
}
SWX类:公共CAD
{
虚拟画圈(Circle*Circle){//在SWX系统上做一些画圈的事情}
}
class PRO:公共CAD
{
虚拟画圈(Circle*Circle){//在PRO系统上做一些画圈的事情}
}
int main()
{
圆圈*圆圈=新圆圈();
Square*sq=新广场;
矢量形状;
形状。推回(圆形);
形状。推回(sq);
SWX*SWX=新的SWX();
对于(int i=0;iAcceptVisitor(SWX);
}
}

在这段代码中,我选择了使
CAD
实际上成为
ShapeVisitor
的一个子类。此外,由于在
CAD
中已经有了绘制图形的虚拟方法,我在那里实现了
Visit
方法(一次),而不是在每个子类中一次。一旦您将客户端切换到使用
AcceptVisitor
而不是直接调用Draw*方法,您就可以保护这些方法,然后最终将
Visit
方法的实现移到子类中(也就是说:重构以消除由于调用
Visit(Foo*)
call
DrawFoo(Foo*)
)而导致的额外间接级别。

这里有一些相当不可靠的OO,但至少DrawXxxx应该变成Draw()。圆形、方形和其他形状将定义Draw())方法,该方法为形状上的虚拟绘制方法提供实现。然后,您可以在任何形状上调用Draw,它将做正确的事情


isXxxx布尔值也应该去。类知道它们是什么,instanceof可以告诉你(尽管不需要检查何时绘制,因为这将是一个虚拟方法调用)。

这是一个典型的例子,在这种情况下,你需要为每个可能的(形状、CAD)对使用一个单独的方法:

  • 核化
    isSquare
    /
    isCircle
    字段
  • 形状
    界面添加
    虚拟空心绘图(CAD*)
  • 实现
    Circle::drawin(CAD*)
    (例如):

    这是一个“技巧”,它允许像
    myCircle->drawin(mySWX)
    这样的调用调用正确的方法,无论形状类型或CAD如何


    • 这可能不是理想的解决方案,但是
      class Circle;
      class Square;
      class ShapeVisitor
      {
          virtual void Visit(Circle *circle) = 0;
          virtual void Visit(Square *square) = 0;
      }
      
      class Shape
      {
          virtual void AcceptVisitor(ShapeVisitor *visitor) = 0;
      }
      
      
      class Circle : public Shape
      {
          // some special members/methods
      
          virtual void AcceptVisitor(ShapeVisitor *visitor)
          {
              visitor->Visit(this);
          }
      }
      
      class Square : public Shape
      {
          // some special members/methods
      
          virtual void AcceptVisitor(ShapeVisitor *visitor)
          {
              visitor->Visit(this);
          }
      }
      
      class CAD : public ShapeVisitor
      {
          virtual DrawCircle(Circle *circle) = 0;
          virtual DrawSquare(Square *square) = 0;
      
          virtual void Visit(Circle *circle) {
              DrawCircle(circle);
          }
      
          virtual void Visit(Square *square) {
              DrawSquare(square);
          }
      }
      
      class SWX : public CAD
      {
          virtual DrawCircle(Circle *circle){// do some stuff that draws circle on SWX system}
      
      }
      
      class PRO : public CAD
      {
          virtual DrawCircle(Circle * circle){// do some stuff that draws circle on PRO system}
      }
      
      int main()
      {
          Circle * circle = new Circle();
          Square * sq = new Square;
      
          vector<Shape*> shapes;
          shapes.push_back(circle);
          shapes.push_back(sq);
      
          SWX * swx = new SWX();
      
          for( int i = 0 ; i < shapes.size() ; ++i )
          {
              shapes[i]->AcceptVisitor(SWX);
          }
      }
      
      void Circle::DrawOn(CAD *c) {
        c->DrawCircle(this);
      }
      
      class CAD {
        public:
          virtual void Draw(const Circle& circle) = 0;
          virtual void Draw(const Square& square) = 0;
      };
      
      class Shape
      {
          virtual void DrawWithCAD(CAD * cad) = 0;
      }
      
      class Circle : public Shape
      {
          virtual void DrawWithCAD(CAD * cad)
          {
              cad->DrawCircle(this);
          }
      }
      
      class Square : public Shape
      {
          virtual void DrawWithCAD(CAD * cad)
          {
              cad->DrawSquare(this);
          }
      }
      
      for( int i = 0 ; i < shapes.size() ; ++i )
      {
          shapes[i]->DrawWithCAD(swx);
      }
      
      void Draw(CAD *cad, Circle *circle){
          cad->DrawCircle(circle);
      }
      
      void Draw(CAD *cad, Square *square){
          cad->DrawSquare(square);
      }
      
      class Shape
      {
          Draw(ICAD* cad) = 0;        
      }
      
      class Circle : public Shape
      {
          Draw(ICAD* cad)
          {
              ICAD->DrawCircle(self)
           }
      }
      
      class Square : public Shape
      {
          Draw(ICAD* cad)
          {
              ICAD->DrawSquare(self)
           }
      }
      
      class ICAD
      {
          virtual DrawSquare(Square* square) = 0;
          virtual DrawCircle(Circle * circle) = 0;
      }
      
      class CAD : public ICAD
      {
          // big CAD class...
      }
      
      class SWX : public CAD
      {
          virtual DrawCircle(Circle * circle){// do some stuff that draws circle on SWX system}
      }
      
      class PRO : public CAD
      {
          virtual DrawCircle(Circle * circle){// do some stuff that draws circle on PRO system}
      }
      
      int main()
      {
          Circle * circle = new Circle();
          Square * sq = new Square;
      
          vector<Shape*> shapes;
          shapes.push_back(circle);
          shapes.push_back(sq);
      
          SWX * swx = new SWX();
      
          for( int i = 0 ; i < shapes.size() ; ++i )
          {
              shapes[i]->Draw(swx);
          }
      }