Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the rules for dynamic dispatching in c++?

I wonder how dynamic dispatching really works in C++. To illustrate my question, I will start by some Java code.

class A
{
  public void op(int x, double y) { System.out.println("a"); }
  public void op(double x, double y) { System.out.println("b"); }
}

class B extends A
{
  public void op(int x, double y) { System.out.println("c"); }
  public void op(int x, int y) { System.out.println("d"); }
}

class C extends B
{
  public void op(int x, int y) { System.out.println("e"); }
}

public class Pol
{
  public static void main(String[] args)
  {
    A a = new C();
    B b = new C();

    /* 1 */ a.op(2, 4);
    /* 2 */ b.op(2.0, 4.0);
  }
}

The call a.op(2, 4) will print "c", since indeed the compiler:

  • looks into Class A (since a is declared to be a variable of type A) which method is the closest to op(int, int),
  • can't find a op(int, int) method but finds the method op(int, double) (with a single auto-cast int -> double),
  • then fixes this signature.

During the execution, the JVM:

  • looks for a method with the signature op(int, double) fixed by the compiler into Class C but doesn't find it,
  • looks inside C's super-class, i.e., B,
  • and finally finds a method op(int, double), then calls it.

The same principle applies to the call b.op(2.0, 4.0), which prints "b".

Now, consider the equivalent code in C++

#include <iostream>

class A
{
public:
  virtual void op(int x, double y) { std::cout << "a" << std::endl; }
  virtual void op(double x, double y) { std::cout << "b" << std::endl; }
};

class B : public A
{
public:
  void op(int x, double y) { std::cout << "c" << std::endl; }
  virtual void op(int x, int y) { std::cout << "d" << std::endl; }
};

class C : public B
{
public:
  void op(int x, int y) { std::cout << "e" << std::endl; }
};

int main()
{
  A *a = new C;
  B *b = new C;

  /* 1 */ a->op(2,  4);
  /* 2 */ b->op(2.0, 4.0);

  delete a;
  delete b;
}

a->op(2, 4) will print "c", like Java. But b->op(2.0, 4.0) outputs "c" again, and there, I'm lost.

What are exactly the rules applied at the compilation and during the execution in C++ for dynamic dispatching? (Notice you will have the same behavior from the C++ code if you write virtual in front of each function; it changes nothing here)

like image 919
Florian Richoux Avatar asked Sep 20 '13 09:09

Florian Richoux


People also ask

Does C have dynamic dispatch?

Yes. It can be easily achieved. You would use an array of function pointers, then use those function pointers to make the call.

What is dynamic dispatch in programming?

In computer science, dynamic dispatch is the process of selecting which implementation of a polymorphic operation (method or function) to call at run time. It is commonly employed in, and considered a prime characteristic of, object-oriented programming (OOP) languages and systems.

What is dynamic dispatch and how does it work in Objective C?

Dynamic dispatch, for example, is one of the features that make Objective-C as dynamic as it is. Dynamic what? Dynamic dispatch. It simply means that the Objective-C runtime decides at runtime which implementation of a particular method or function it needs to invoke.

What is meant by dynamic dispatch give any example?

Dynamic method dispatch is the mechanism in which a call to an overridden method is resolved at run time instead of compile time. This is an important concept because of how Java implements run-time polymorphism.


1 Answers

For C++, when you do b->op(2.0, 4.0); the compiler looks in B, finds a method it can call (int x, double y) and uses it. It does not look in the superclass if any method in the subclass can handle the call. This is called method hiding, ie. op(double, double) is hidden.

If you want to make it select the (double x, double y) version, you need to make the function visible inside of B with the following declaration inside B:

using A::op;

Further explanation of the rules

like image 72
Hampus Nilsson Avatar answered Sep 23 '22 13:09

Hampus Nilsson