在c ++中动态调度的规则是什么?

Flo*_*oux 10 c++ polymorphism

我想知道动态调度在C++中是如何工作的.为了说明我的问题,我将从一些Java代码开始.

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);
  }
}
Run Code Online (Sandbox Code Playgroud)

调用a.op(2, 4)将打印"c",因为编译器确实如此:

  • 查看Class A(因为a声明为类型的变量A)哪个方法最接近op(int, int),
  • 找不到op(int, int)方法但找到方法op(int, double)(使用单个自动转换int- > double),
  • 然后修复此签名.

在执行期间,JVM:

  • 寻找一个方法,将op(int, double)编译器固定的签名固定到Class中,C但找不到它,
  • 看看C的超级类,即B,
  • 最后找到一个方法op(int, double),然后调用它.

同样的原则适用于b.op(2.0, 4.0)打印"b" 的调用.

现在,考虑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;
}
Run Code Online (Sandbox Code Playgroud)

a->op(2, 4)将像Java一样打印"c".但是b->op(2.0, 4.0)再次输出"c",在那里,我迷失了.

在C++中用于动态调度的编译和执行期间应用的规则是什么?(请注意,如果virtual在每个函数前面写入,那么C++代码将具有相同的行为;它在此处不会更改)

Ham*_*son 3

对于 C++,当您执行b->op(2.0, 4.0);编译器查找时B,会找到它可以调用并使用它的方法(int x, double y)。它不会在超类中查找子类中是否有任何方法可以处理该调用。这称为方法隐藏,即。op(double, double)被隐藏。

如果你想让它选择版本(double x, double y),你需要使函数在内部可见B,并在内部声明以下B

using A::op;
Run Code Online (Sandbox Code Playgroud)

规则的进一步解释