我试图了解编译器何时拥有或不拥有决定静态或动态地将方法调用绑定到方法定义所需的所有信息。
我读到在Java中有一个规则,当方法被重载时静态绑定它们,当方法被覆盖时动态绑定它们。
例如,如果我有:
class A
{
public:
// virtual void p()
void p() {
cout << "A::p" << endl;
}
void q() {
p();
}
};
class B : public A
{
public:
void p() {
cout << "B::p" << endl;
}
};
a)当我这样做时:
A a;
B b;
a.q(); // output: A::p
b.q(); // output: A::p
我假设编译器(g++)静态地将b.q()
绑定到A.q()
,将p()
(在A.q()
内)绑定到A.p()
。
B)但是,如果我将A.p()
声明为virtual,则输出将为:
a.q(); // output: A::p
b.q(); // output: B::p
这里,我假设b.q()
静态地绑定到A.q()
,就像前面的场景一样,但是A.q()
中的p()
绑定到B.p()
,它覆盖了A.p()
。
如果规则是相同的(重写是动态解决的),这将意味着编译器没有静态执行重写所需的所有信息。
为什么编译器不能绑定虚拟方法的重写版本,而不是将该决定交给运行时?这里缺少的信息是什么?
===〉已编辑〈===
有人建议不要混合Java和C++。我正在阅读Louden & Lambert的书《编程语言》,作者比较了这两种语言中的绑定。这就是我提到它们的原因。但是,我的问题更多的是关于动态链接的需要,而不管是什么语言。为什么编译器不能根据源代码计算出如何绑定虚拟或重写方法?
1条答案
按热度按时间46qrfjad1#
C++使用虚方法表来支持动态调度。类的示例包含指向结构的隐藏指针,该结构包含该类的
virtual
方法的函数指针。举个简单的例子:
编译器事先不知道对
ap->p();
的调用实际上会调用什么代码。some_function
可以被编译成目标代码,位于库中或链接到可执行文件,运行和调用ap-p>();
,并执行在编译some_function
时实际上不存在的代码。