重写方法的动态绑定:为何编译器无法静态绑定虚方法?
静态绑定与动态绑定的核心疑问
我想搞明白编译器什么时候能获取到绑定方法调用与定义的全部信息,什么时候不能。我知道Java里的规则:重载方法用静态绑定,重写方法用动态绑定。但通过C++代码做实验后,对其底层机制不太清楚。
示例代码
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(),同时A.q()里的p()也静态绑定到A.p(),因为A.p()处于A.q()的上下文当中。
b) 虚方法场景
如果把A.p()声明为virtual,输出结果变为:
a.q(); // output: A::p b.q(); // output: B::p
此时我认为b.q()还是和之前一样静态绑定到A.q(),但A.q()中的p()会绑定到重写A.p()的B.p()。
核心疑问
按照重写需要动态解析的规则,说明编译器没有静态绑定所需的全部信息。那为什么编译器不能直接绑定重写后的虚方法,非要把决策延迟到运行时?到底缺失了什么信息?
补充说明
有人建议不要混淆Java和C++,我正在阅读Louden & Lambert所著的《Programming Languages》一书,作者对比了两种语言的绑定机制,这也是我提及Java的原因。但我的问题更多关乎动态绑定的必要性,和具体语言无关:为什么编译器无法仅通过源代码就确定如何绑定虚方法或重写方法?
内容的提问来源于stack exchange,提问作者aledruetta
相关产品推荐
相关产品推荐

