为什么静态解析虚拟方法调用如此困难?
假设我们有以下伪代码。我说的是 OO 语言。
class A{
foo(){...}
}
class B extends A{
foo(){...}
}
class C extends B{
foo(){...}
}
static void f(A a)
{
A a=new A();
a=new B();
a.foo();
}
我们很容易认识到a.foo()正在调用B类中重写的函数foo。那么为什么编译器很难通过静态分析得到这个事实呢?这里的基本问题是为什么静态确定 A 的类型对于编译器来说很难?
Suppose we have the following pseudo code. I am talking about OO languages.
class A{
foo(){...}
}
class B extends A{
foo(){...}
}
class C extends B{
foo(){...}
}
static void f(A a)
{
A a=new A();
a=new B();
a.foo();
}
It's easy for us to recognize that a.foo() is calling function foo overridden in class B. So why it's hard for compilers to get this truth by static analysis? The fundamental question here is why statically determine the type of A is hard for a compiler?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您发布的示例非常简单,没有显示任何需要虚拟方法调用的内容。使用相同的类,检查此函数;
编译器无法在编译时判断
a
是B
的实例、还是C
还是普通的一个。一般情况下,这只能在运行时决定。
编译器甚至无法知道在将来的某个时刻是否会有从
A
派生的新类与此代码链接。The example you posted is extremely simplistic and does not show anything that requires a virtual method call. With your same classes, examine this function;
There is no way the compiler can tell at compile-time if
a
is an instance ofB
, orC
, or a plainA
. That can only be decided at runtime in the general case.The compiler can't even know if there will be new classes derived from
A
at some future point that will be linked with this code.想象一下:
现在你完蛋了。
严肃地说,你的例子太简单了。想象一下,如果赋值的右侧是对其他“模块”中定义的函数的调用(无论这意味着什么)。这意味着编译器必须检查所有执行路径才能确定返回值的确切类型,但这是非常昂贵的,有时甚至是根本不可能的。
Just imagine:
Now you're screwed.
On a serious note, your example is way too simplistic. Imagine if a right-hand side of an assignment is a call to a function defined in some other "module" (whatever this means). This means that the compiler has to inspect all execution paths in order to determine the exact type of a return value, but that's prohibitively expensive and sometimes downright impossible.