http://hi.baidu.com/hj11yc/item/0428b1ba2c7e8aadeaba93b3
另外:
可参考:
http://blog.csdn.net/haoel/article/details/3081385
我们来看看有虚函数,并且是有虚基类的类的内存布局
我们看看一个有成员的例子:
#include<iostream>
using namespace std;
class A{
public:
int a;
A():a(1){}
virtual void show(void){cout<<"call A"<<endl;}
};
class B:virtual public A{
public:
int b;
B():b(2){}
virtual void show(void){cout<<"call B"<<endl;}
};
class C:virtual public A{
public:
int c;
C():c(3){}
virtual void show(void){cout<<"call C"<<endl;}
};
class D:public B,public C{
public:
int d;
D():d(4){}
virtual void show(void){cout<<"call D"<<endl;}
};
int main(void)
{
D d;
cout<<"the address begin:"<<&d<<endl;
cout<<""<<endl;
cout<<hex<<*(((int *)&d)+0)<<endl;
cout<<hex<<*(((int *)&d)+1)<<endl;
cout<<hex<<*(((int *)&d)+2)<<endl;
cout<<hex<<*(((int *)&d)+3)<<endl;
cout<<hex<<*(((int *)&d)+4)<<endl;
cout<<hex<<*(((int *)&d)+5)<<endl;
cout<<hex<<*(((int *)&d)+6)<<endl;
cout<<hex<<*(((int *)&d)+7)<<endl;
cout<<hex<<*(((int *)&d)+8)<<endl;
cout<<hex<<*(((int *)&d)+9)<<endl;
system("pause");
return 1;
}
输出来看看呢?
可以看个大概是怎么分布的,但是哪些是vptr,社么是vbptr呢》》?????
来看个详细的例子
#include<iostream>
using namespace std;
class A{
public:
int a;
A():a(1){}
virtual void show(void){cout<<"call A"<<endl;}
};
class B:virtual public A{
public:
int b;
B():b(2){}
virtual void show(void){cout<<"call B"<<endl;}
};
class C:virtual public A{
public:
int c;
C():c(3){}
virtual void show(void){cout<<"call C"<<endl;}
};
class D:public B,public C{
public:
int d;
D():d(4){}
virtual void show(void){cout<<"call D"<<endl;}
};
typedef void (*FUN )(void);
int main(void)
{
D d;
cout<<"the address begin:"<<&d<<endl;
cout<<""<<endl;
cout<<hex<<*(((int *)&d)+0)<< " ";cout<<dec<<*((int *)(*((int *)&d+0))+0)<<" ";cout<<dec<<*((int *)(*((int *)&d+0))+1)<<endl;
cout<<hex<<*(((int *)&d)+1)<<endl;
cout<<hex<<*(((int *)&d)+2)<<" ";cout<<dec<<*((int *)(*((int *)&d+2))+0)<<" ";cout<<dec<<*((int *)(*((int *)&d+2))+1)<<endl;//这两个都是指向virtual base table的指针,第一项都为0,第二项是偏移量
cout<<hex<<*(((int *)&d)+3)<<endl;
cout<<hex<<*(((int *)&d)+4)<<endl;
cout<<hex<<*(((int *)&d)+5)<<endl;
cout<<hex<<*(((int *)&d)+6)<<" ";cout<<dec<<*((int *)(*((int *)&d+6))+0)<<" ";
cout<<hex<<*(((int *)&d)+7)<<endl;
cout<<hex<<*(((int *)&d)+8)<<endl;
cout<<hex<<*(((int *)&d)+9)<<endl;
cout<<"//"<<endl;
/*FUN fun11=(FUN)*((int *)(*((int *)&d+0))+0);
fun11();
fun11=(FUN)*((int *)(*((int *)&d+2))+0);
fun11();*这两个不能运行,说明没有指向函数,则说明类中的第一个,第三个数据是指向基类的指针。并且在上面的输出中可以看到这两个指针的第一项都为0,说明没有虚函数,这个没有虚函数说的是没有自己独特于基类的虚函数。所以第一项为0,第二项为偏移量。
FUN fun11=(FUN)*((int *)(*((int *)&d+6))+0);
fun11();
/*fun11=(FUN)*((int *)(*((int *)&d+6))+1);
fun11();*///这个也不能,因为只有一个虚函数,并且是三个共用的,所以上面一个能运行,这个不能
system("pause");
return 1;
}
看看结果:
可以看到什么问题么??看看我嗦分析的。也许你看到注释分析的过后会问,B,C的vptr呢?因为他们没有自己的虚函数,所以没有产生,只有vbptr,是偏移量。所以都指向了基类的vptr处。
如果不相信,你可以为B单独添加一个虚函数,然后你就知道了。不信来看看:
#include<iostream>
using namespace std;
class A{
public:
int a;
A():a(1){}
virtual void show(void){cout<<"call A"<<endl;}
};
class B:virtual public A{
public:
int b;
B():b(2){}
virtual void show(void){cout<<"call B"<<endl;}
virtual void go(void){cout<<"call B:;go"<<endl;}
};
class C:virtual public A{
public:
int c;
C():c(3){}
virtual void show(void){cout<<"call C"<<endl;}
};
class D:public B,public C{
public:
int d;
D():d(4){}
virtual void show(void){cout<<"call D"<<endl;}
};
typedef void (*FUN )(void);
int main(void)
{
D d;
cout<<"the address begin:"<<&d<<endl;
cout<<""<<endl;
cout<<hex<<*(((int *)&d)+0)<< endl;
cout<<hex<<*(((int *)&d)+1)<<" ";cout<<dec<<*((int *)(*((int *)&d+1))+0)<<" ";cout<<dec<<*((int *)(*((int *)&d+1))+1)<<endl;
cout<<hex<<*(((int *)&d)+2)<<endl;
cout<<hex<<*(((int *)&d)+3)<<endl;
cout<<hex<<*(((int *)&d)+4)<<endl;
cout<<hex<<*(((int *)&d)+5)<<endl;
cout<<hex<<*(((int *)&d)+6)<<endl;
cout<<hex<<*(((int *)&d)+7)<<endl;
cout<<hex<<*(((int *)&d)+8)<<endl;
cout<<hex<<*(((int *)&d)+9)<<endl;
cout<<"//"<<endl;
FUN fun11=(FUN)*((int *)(*((int *)&d+0))+0);
fun11();
system("pause");
return 1;
}
我只为B增加了一个自己的虚函数,看看输出呢?
再解释下-4的含义,意思就是说有自己的虚函数,如果没有的话,这个值是0;24是偏移量,记住,基类偏移量