下面是一个写的超级好的blog,详细解释了类的内存分布以及虚函数的调用方式。。膜拜之。。
下面是我写的一个测试代码。。关于内存分布参见上面链接
代码中主要测试了类的内存分布不同时,指针引用强转可能出现的情况,发现现在的编译器真是做的好。
指针和引用在类继承体系中强转,对应的地址也会改变以指向对象中对应要转向类型部分的起始地址,只有在先强转成void*再转时才出错,因为viod*没有类型,编译器也不知道怎么办,只好还是原地址了
#include <iostream>
using namespace std;
class A {
public:
A(int a): _a(a) {
cout << "A" << endl;
}
virtual void a() {
cout << "A::a()" << endl;
}
private:
long long _a;
};
class B: virtual public A{
public:
B(int a): A(a) {
cout << "B" << endl;
}
};
class C: virtual public A{
public:
C(int a): A(a) {
cout << "C" << endl;
}
virtual void c() {
cout << "C::c()" << endl;
}
};
class D: public B, public C {
public:
D(int a): B(a), C(a), A(a) {
cout << "D" << endl;
}
};
//引用导致地址偏移,而且可以看到B,D的地址是一样的
void fa(A& a) {
cout << "A& " << (size_t)&a << endl;
a.a();
}
void fb(B& a) {
cout << "B& " << (size_t)&a << endl;
a.a();
}
void fc(C& a) {
cout << "C& " << (size_t)&a << endl;
a.a();
}
void fd(D& a) {
cout << "D& " << (size_t)&a << endl;
a.a();
}
void test() {
D d(10);
fa(d);
fb(d);
fc(d);
fd(d);
}
int main(int argc, char* argv[]) {
D d(10);
cout << sizeof(A) << " " << sizeof(B) << " " << sizeof(C) << " " << sizeof(D) << endl;
//16 24 24 32 (64位机器)
//A(虚函数表指针+ longlong)
//B(自身虚函数表指针 +A)
//C(自身虚函数表指针 +A)
//D(自身虚函数表指针(整合B虚函数表指针) +C虚函数表指针+A )
D* x = new D(10);
x->a();
x->c();
cout << (size_t)(x) << endl; //打印地址
void *t = (void*) x; //强转为void* 保证地址不变
C* tt = (C*)t;
cout << (size_t)(tt) << endl;
//tt->c(); 报错,因为第一个虚函数表为B的虚函数表,内部没有c()函数指针
C* c = x; //地址偏移,c指向类D中C的虚函数表
cout << (size_t)(c) << endl;
c->c(); //调用成功
c = static_cast<C*>(x); //地址偏移同上
cout << (size_t)(c) << endl;
c->c();
C* p;
p = x;
cout << (size_t)(p) << endl;
p->c();
D* pp;
pp = dynamic_cast<D*>(p);
//下面两种写法效果相同,地址都会再回到D的虚函数表位置
// pp = (D*)p;
cout << (size_t)pp << endl;
p->c();
cout << "---------------" << endl;
test();
return 0;
}
程序输出:
A
B
C
D
16 24 24 32
A
B
C
D
A::a()
C::c()
140495917435808
140495917435808
140495917435816
C::c()
140495917435816
C::c()
140495917435816
C::c()
140495917435808
C::c()
---------------
A
B
C
D
A& 140734617348608
A::a()
B& 140734617348592
A::a()
C& 140734617348600
A::a()
D& 140734617348592
A::a()