我想知道动态调度在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",因为编译器确实如此:
A
(因为a
声明为类型的变量A
)哪个方法最接近op(int, int)
,op(int, int)
方法但找到方法op(int, double)
(使用单个自动转换int
- > double
),在执行期间,JVM:
op(int, double)
编译器固定的签名固定到Class中,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++代码将具有相同的行为;它在此处不会更改)
对于 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)