Why can polymorphism be used to replace switch or else-if statements?

I am a little confused by what I read in the post: case-vs-if-else-if-which-is-more-efficient

Many times it has been suggested that long case / if-else statements should be replaced with polymorphism. I am trying to understand what this means. How can you replace:

case TASK_A:
    // do things for task A
    break;
case TASK_B:
    // do things for task B
    break;
        :
        :
case TASK_J:
    // do things for task J
    break;

With polymorphism? I could understand this if the “do ...” part is basically the same repetition, but if there are significant differences between some or all of the “cases,” then is this still applicable?

+4
source share
6 answers

, , switch , - , . , , , , switch .

, . , :

struct Task         {virtual void do_things() = 0;};
struct TaskA : Task {virtual void do_things() {/*do things for task A*/}};
struct TaskB : Task {virtual void do_things() {/*do things for task B*/}};
//...
struct TaskJ : Task {virtual void do_things() {/*do things for task J*/}};

, , () Task; task->do_things(). , , switch, .

+4

/, . task, ( ), ; handle_task

(.. case ) // do things for task X handle_task

- / , handle_task .

:

#include <iostream>

class Task {
  public:
    virtual void handle_task()
    {
      std::cout << "Parent task" << std::endl;
    }
};

class Task_A: public Task {
  public:
    void handle_task()
    {
      std::cout << "task a" << std::endl;
    }
};

class Task_B: public Task {
  public:
    void handle_task()
    {
      std::cout << "task b" << std::endl;
    }
};

int main( void )
{
  Task *task;
  Task_A a;
  Task_B b;

  task=&a;
  task->handle_task();
  task=&b;
  task->handle_task();

}

/tmp$ g++ test.cpp
/tmp$ ./a.out
task a
task b
+4

, , . , , ( ).

C, :

// Switch-based:

void do_something(int action, void * data)
{
    switch(action)
    {
        case 1: foo(data); break;
        case 2: bar(data); break;
        case 3: zip(data); break;
        default: break;
    }
}

// Polymorphic:

typedef void (*action_func)(void *);

void do_something(action_func f, void * data)
{
    f(data);
}

, , , .

+3

. , . . ,

  • .

, - .

. , switch. , ( !), , - libarry, . , .

  BaseTask = class
  {
    virtual void Perform() = 0;
  }

  TaskOne = class(BaseTask)
  {
    void Perform() { cout << "Formatting hard disk ..."; }
  }

  TaskTwo = class(BaseTask)
  {
    void Perform() { cout << "Replacing files with random content ..."; }
  }

,

foreach( BaseTask task in Tasks)  // pseudo code    
{
  task.Perform();
}

, :

  TaskThree = class(BaseTask)
  {
    void Perform() { cout << "Restoring everything form the backup..."; }
  }

. , . ?

+2

: Animal, 2 : Dog Bird

feed(), , Dog Bird.

:

if object is dog
    object.dog.feed()
else
    object.bird.feed()

:

object.feed()
0

Base - do_task(). DerivedA, DerivedA.. DerivedJ Base, do_task. :

std::shared_ptr<Base> obj = // points to a Derivedx

// ....

obj->do_task()
0

All Articles