C++派生类指针赋值给基类指针后,指针变量的值发生改变

例1

class A {
public:
    int m_a;
};

class B {
public:
    int m_b;
};

class C : public A, public B {
public:
    int m_c;
};

int main()
{
    C c;
    A* pa = &c;
    B* pb = &c;
    void* pc = &c;
    printf("%p\n%p\n%p\n", pa, pb, pc);
    return 0;
}

输出结果:

pa=0133F59C
pb=0133F5A0
pc=0133F59C

为啥pb的值和pc的值不一样呢?派生类指针转成基类指针时,派生类独有的部分会被丢弃掉,比方说对象c里有一个m_a的内存区间是对象b里没有的,当把c的指针转成b的指针时,m_a对应的内存区间会被丢弃,所以发生了pb和pc的值不相等的情况。

例2

class A {
public:
    virtual void f() {}
};

class B{
public:
    int m_b;
};

class C : public A, public B {
};

int main()
{
    C c;
    A* pa = &c;
    B* pb = &c;
    void* pc = &c;
    printf("%p\n%p\n%p\n", p1, p2, p3);
    system("pause");
    return 0;
}

这里的输出结果,pb和pc同样是不相等的。因为有虚函数的对象,会有一个指向虚函数表的指针变量,这个变量的内存是在其他成员变量之前的,占一个指针变量那么宽的内存空间。

关于虚函数的内存的其他知识

从内存角度来看,虚函数被覆盖后则相当于另一个函数了

如果派生类的虚函数覆盖了基类的虚函数,那么这两个函数地址是不同的。如果派生类只是继承了基类的虚函数,并没有覆盖它,那么这两个函数的地址是相同的。

#include <cstdlib>
#include <cstdio>

class A {
public:
    virtual void fa() {}
};

class B : public A {
};

class C : public A {
public:
    virtual void fa() override {}
};

int main()
{
    A a;
    B b;
    C c;
    //可以断点查看,三个对象里的虚函数指针的值,a和b是一样的,但是c和ab不一样。
    return 0;
}