Multiple dispatch in C++

前端 未结 3 738
梦毁少年i
梦毁少年i 2020-11-27 04:29

I am trying to understand what multiple dispatch is. I read a lot of various texts but I still have no idea what multiple dispatch is and what it is good for. Maybe the thin

相关标签:
3条回答
  • 2020-11-27 04:42

    Multi-dispatch is the ability to choose which version of a function to call based on the runtime type of the arguments passed to the function call.

    Here's an example that won't work right in C++ (untested):

    class A { };
    class B : public A { };
    class C : public A { }
    
    
    class Foo
    {
      virtual void MyFn(A* arg1, A* arg2) { printf("A,A\n"); }
      virtual void MyFn(B* arg1, B* arg2) { printf("B,B\n"); }
      virtual void MyFn(C* arg1, B* arg2) { printf("C,B\n"); }
      virtual void MyFn(B* arg1, C* arg2) { printf("B,C\n"); }
      virtual void MyFn(C* arg1, C* arg2) { printf("C,C\n"); }
    };
    
    void CallMyFn(A* arg1, A* arg2)
    {
      // ideally, with multi-dispatch, at this point the correct MyFn() 
      // would be called, based on the RUNTIME type of arg1 and arg2
      pFoo->MyFn(arg1, arg2);
    }
    
    ...
    
    A* arg1 = new B();
    A* arg2 = new C();
    // Using multi-dispatch this would print "B,C"... but because C++ only
    // uses single-dispatch it will print out "A,A"
    CallMyFn(arg1, arg2);
    
    0 讨论(0)
  • 2020-11-27 04:48

    Multiple dispatch is when the function that gets executed depends on the run time type of more than one object.

    C++ has single dispatch because when you use virtual functions, the actual function that gets run depends only on the run-time type of the object to the left of the -> or . operator.

    I'm struggling to think of a real programming case for multiple dispatch. Maybe in a game where various characters fight each other.

    void Fight(Opponent& opponent1, Opponent& opponent2);
    

    The winner of a fight may depend on the characteristics of both opponents, so you may want this call to dispatch to one of the following, depending on the run-time types of both arguments:

    void Fight(Elephant& elephant, Mouse& mouse)
    {
        mouse.Scare(elephant);
    }
    
    void Fight(Ninja& ninja, Mouse& mouse)
    {
        ninja.KarateChop(mouse);
    }
    
    void Fight(Cat& cat, Mouse& mouse)
    {
        cat.Catch(mouse);
    }
    
    void Fight(Ninja& ninja, Elephant& elephant)
    {
        elephant.Trample(ninja);
    }
    
    // Etc.
    

    What the function does depends on the types of both arguments, not just one. In C++ you might have to write this as some virtual functions. A virtual function would be selected depending on one argument (the this pointer). Then, the virtual function may need to contain a switch or something to do something particular to the other argument.

    0 讨论(0)
  • 2020-11-27 04:53

    In single dispatch the function executed depends on just the object type. In double dispatch the function executed depends on the object type and a parameter.

    In the following example, the function Area() is invoked using single dispatch, and Intersect() relies on double dispatch because it takes a Shape parameter.

    class Circle;
    class Rectangle;
    class Shape
    {
        virtual double Area() = 0; // Single dispatch
    
        // ...
        virtual double Intersect(const Shape& s) = 0; // double dispatch, take a Shape argument
        virtual double Intersect(const Circle& s) = 0; 
        virtual double Intersect(const Rectangle& s) = 0; 
    };
    
    struct Circle : public Shape
    {
        virtual double Area() { return /* pi*r*r */; }
    
        virtual double Intersect(const Shape& s); 
        { return s.Intersect(*this)  ; }
        virtual double Intersect(const Circle& s); 
        { /*circle-circle*/ }
        virtual double Intersect(const Rectangle& s); 
        { /*circle-rectangle*/ }
    };
    

    The example is based on this article.

    0 讨论(0)
提交回复
热议问题