假设我们有以下伪代码。我说的是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的类型对编译器来说很难?
答案 0 :(得分:3)
您发布的示例非常简单,并且不显示需要虚拟方法调用的任何内容。使用相同的类,检查此函数;
void bar(A* a) {
a->foo();
}
如果a
是B
,C
或普通A
的实例,则编译器无法在编译时告知。这只能在一般情况下在运行时决定。
编译器甚至无法知道是否会在将来与A
派生的新类与此代码链接。
答案 1 :(得分:2)
想象一下:
A a = createInstanceFromString("B");
现在你搞砸了。
严肃地说,你的例子太简单了。想象一下,如果赋值的右侧是对某个其他“模块”中定义的函数的调用(无论这意味着什么)。这意味着编译器必须检查所有执行路径以确定返回值的确切类型,但这非常昂贵,有时甚至是不可能的。