Class A Class B: public A
{ {
private: private:
int a; int b;
public: public:
void fn1(){cout<<"A fn1()"<<endl;} void fn2(){cout<<"B fn2()"<<endl;}
virtual void fn2(){cout<<"A fn2()"<<endl;} virtual void fn3(){cout<<"B fn3()"<<endl;}
}; void fn4(){cout<<"B fn4()"<<endl;}
};
Class A ‘s object model
vptr
|
int a
|
Class A ‘s vtbl
Type_info
|
Virtual Fn2()
|
Class B’s object model
vptr
|
Int a
|
Int b
|
Class B’s vtbl
Type_info
|
Virtual fn2()
|
Virtual fn3()
|
Main()
{
A* pA=new B; // pA始终认为自己是指向A object的指针。即使实际指向B object,pA也只能采用A
// 定义的部分,实际上,因为B中有着和A完全一样的部分(结构一样,内容可能不
// 同,像virtual fn2()),我们用B中继承的A部分来替代A,欺骗了编译器。
// 所以,pA是无法访问B中除了A subobject之外的其他部分的。
pA->fn2(); // ok, 调用B::fn2()
pA->fn3(); // not ok. Fn3() 在B中定义
pA->fn4(); // not ok。Fn4() 在B中定义
reinterpret_cast<B*>(pA)->fn3(); // ok
// 将pA强制转换成B*,因为pA指向的恰好就是一个B对象。
pA->fn1(); // ok, 正常调用A::fn1(),传给fn1()的this就是A*指针,而不是B*
// pA从来就不是pB.
}
这里,重温一下多态成立的条件:
1. 基类指针被赋值为子类指针
2. 该指针调用virtual函数。
该不会奇怪为什么要同时满足这两个条件了吧。
基类指针仍然只能识别基类范围的内容,只是virtual函数已经把内容替换了,而基类指针无从察觉罢了。