c++11 学习及测试(虚继承 虚函数时类的内存分布)

下面是一个写的超级好的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()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值