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函数已经把内容替换了,而基类指针无从察觉罢了。