上述的输出全部都是"B1"。
原因是表达式1在执行名称查找时,首先去A1类中查找(因为a1的类型显式类型是A1指针),发现P()是一个虚函数,因此就会从a1对象中的虚函数表中查找P()的函数指针,发现此函数指针指向的是B1::P()。然后B1::P()中调用了print(),因此直接在类B1中查找print(),如果找不到的话,编译器会继续到类B1作用域的上层,即类A1的作用域中查找print()名称(所以如果你把B1::print()注释掉的话,最终结果都是"A1"),编译器在B1中找到了print(),并发现它不是虚函数,因此不会去a1对象的虚函数表中查找print(),因此最终调用的就是B1::print();
表达式2和3在执行名称查找时,跟表达式1一样,因为P()是虚函数,所以会从对应的对象的虚函数表中查找;
表达式4执行名称查找时,会先从B1对象中查找名称P()(因为b11的显式类型是B1指针),发现P()是一个虚函数,因此会从对象b11的虚函数表中查找P()的地址。由于b11对应的实际类型C1并没有重载P(),因此内存中b11对象的虚函数表中P()的指针仍然是B1::P(),并没有被覆写。接着查找在B1::P()中看到了名字print(),并继续查找print(),且查找过程同上面的分析一致,所以最终调用的也是B1::print();
表达式5看到P()时会先到类B2的作用域里面查找,发现找不到,因此就会扩大查找范围,到B2类的基类B1中查找,结果找到了。然后的分析过程就跟上面一样了,最终也是调用的B1::print()。 如果