我们先回复一下多态,看下面一个例子
#include "stdafx.h"
class A1
{
public:
virtual void sample(int a,int b)=0;
};
class B1 :public A1
{
public:
virtual void sample (int a,int b){trace(“class B1:: sample”);};
};
class C1:public A1
{
public:
virtual void sample (int a,int b){ trace(“class C1:: sample”);};
};
int main(int argc, char* argv[])
{
A1 a1,a2;
B1 b1
C1 c1;
a1=&b1;
a2=&b2;
/
a1->sample(2,3);
a2->sample(1,3);
//
return 0;
}
根据多态的特性a1->sample(2,3)调用的实际上是class B1:: sample
a2->sample(2,3)调用的实际上是class C1:: sample
这是一个最经典的多态的例子了,这里我们不做过多解释!
自以为对多态有了很深的了解,但是下面这个例子起初使我一头雾水,”自高”的心态也就瓦解了,但总算功夫不负有心头人,总算搞清楚原因了,先看看这个例子!
#include "stdafx.h"
class A1
{
public:
virtual void sample(int a,int b){};
};
class B1
{
public:
virtual void sample1(int a,int b){};
virtual void sample2(int a,int b){};
virtual void sample3(int a,int b){};
};
class C1:public A1,public B1
{
public:
virtual void sample2(int a,int b){};
virtual void sample1(int a,int b){};
virtual void sample(int a,int b){};
void setA1(void** a){*a=(A1*)this; }
void setB1(void** b){*b=(B1*)this; }
};
int main(int argc, char* argv[])
{
A1 *a1,*b2;
C1 c1;
c1.setA1((void**)&a1);
c1.setB1((void**)&b2);
a1->sample(2,3);
b2->sample(1,3);
return 0;
}
按照经典的例子看a1->sample(2,3); b2->sample(1,3);这个两个调用的应该都是class C1:: sample(),令人遗憾的是a1->sample(2,3)是我们所希望看到的调用class C1:: sample(),而b2->sample(1,3);调用的却是class C1:: sample1(),这是为什么那!
下面就是我跟踪DEBUG看到的结果
根据上图!原因也就一幕了然了!
调用c1.setA1((void**)&a1);的时候,因为类CA1的原结构中虚函数表中就一项,这时候通过
*a=(A1*)this;的赋值过程,使得CA1的指针a1指向的就是c1中子对象A1虚函数表中的c1::sample(int,int).
调用c1.setB1((void**)&b1);的时候,因为类CA1的原结构中虚函数表中就一项,这时候通过
*a=(B1*)this;的赋值过程, 使得CA1的指针b1指向的就是c1中子对象B1虚函数表中第一项c1::sample1(int,int),其它的表项也就同时被切割掉了,这就解释了为什么b2->sample(1,3)为什么会转到c1::sample1(int,int)的不解了!也就是说这种情况下的赋值只有c1中子对象B1虚函数表中的第一项才被复制给b1指针!!