对虚函数来说,其实际调用的函数要根据调用者实际的类型来决定调用那一个函数。这个具体调用哪一个是在运行的时候去决定的,编程的时候不需要指明。pb->B::fa(); 这一句里你就是要指明pb去调用B类的成员函数fa(),而pb是一个A类型的对象指针,这当然是不行的了。
换句话来说:pb->fa(),这里面调用的实际上就是B类的fa(),但是这一点系统运行的时候可以这么干,但是由你指出来让他这么干,指明要它去调用B类的fa()还就是不允许。
gcc 4.3.2 编译器
a.cpp:29: error: 'B' is not a base of 'A'
B 不是 A 的基类.
我的分析:
A 一个小环境
B 一个中环境,B含了A
A *pa=new A;
A *pb=new B;
上面两句分别把 A 和 B 声名成了A对象。
既然是A对象,那么就要使用A环境,也就是说,pa和pb的空间是A(可以参考命名空间,空间的意思差不多)在A的类空间中,是不包含B类空间的。所以找不到。 上面整个过程 和B类空间没有任何关系。
A *pb = new B; 只是让一个A指针指向B结构。A和B中的变量、函数的位置相对于 A这个struct来说,都是对应的,A中存在一个叫fa的函数指针,B中也存在,而且B中的这个fa指针和A中的位置还是相同的呢。 所以 pb.fa 可以正确找到B环境中的fa函数。 而pb->A::fa(); 这样就要从pb的A子环境中寻找fa函数,由于这个pb并不是真实的A,它其实是B,它有这个子环境,那么就可以找到pb中A子环境中的fa。 但要知道此时,pb就是被强制当作A的B,它们许多指针的排列结构相同,所以可以强制。如果是 pb->B::fa(); 那就找不到了,pb是一个混乱的东西,它虽然是A结构,但是它超出A结构大小的部分却是不规则的,里面又包含了一个A结构。 pb它的主结构就是B,里面不包含B这个子结构了,所以也就出错了。
很复杂吗难道?
简单说,就是编译器不允许基类去(无论显式还是隐式)调用派生类的成员!能够多态是因为有虚函数表!
理由很简单:基类不知道是谁派生的它,它不认识B!
呵呵,好乱呀~我不懂哦,偶是小屁孩,什么虚函数,偶都不知道啥米意思嘛……