Почему статически разрешать вызовы виртуальных методов так сложно? - PullRequest
2 голосов
/ 18 апреля 2011

Предположим, у нас есть следующий псевдокод. Я говорю о ОО языках.

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 () вызывает функцию foo, переопределенную в классе B. Так почему компиляторам трудно получить эту истину статическим анализом? Основной вопрос здесь заключается в том, почему статически определить тип A сложно для компилятора?

Ответы [ 2 ]

3 голосов
/ 18 апреля 2011

Пример, который вы опубликовали, очень прост и не показывает ничего, что требует вызова виртуального метода.Используя те же классы, изучите эту функцию;

void bar(A* a) {
  a->foo();
}

Компилятор не сможет определить во время компиляции, является ли a экземпляром B, или C, или простымA.Это может быть решено только во время выполнения в общем случае.

Компилятор даже не может знать, будут ли новые классы, производные от A, в какой-то момент в будущем, которые будут связаны с этим кодом.*

2 голосов
/ 18 апреля 2011

Только представьте:

A a = createInstanceFromString("B");

Теперь вы облажались.

Если серьезно, ваш пример слишком упрощен.Представьте себе, если правая часть присваивания - это вызов функции, определенной в каком-то другом «модуле» (что бы это ни значило).Это означает, что компилятор должен проверять все пути выполнения, чтобы определить точный тип возвращаемого значения, но это непомерно дорого, а иногда и просто невозможно.

...