c++父类与子类的this指针与虚函数表指针

今天遇到一个很有趣的c++写法,将其写成一个小例子分析一波。
头文件:
#ifndef DEMO1_H_
#define DEMO1_H_

#include <iostream>
#include <typeinfo>
using namespace std;

class B;
class A
{
public:
    static B* s_cP;
};

class B
{
public:
    B() 
    {
        A::s_cP = this;
        cout << "this B:" << this << endl;
    }
    void Do() {cout << "B Do" << endl;}
};

class C : public B
{
public:
    C()
    {
        cout << "this C:" << this << endl;
    }
    void Do() {cout << "C Do" << endl;}
};

#endif

cpp文件

#include "demo1.h"

B* A::s_cP = NULL;

int main()
{
    C c;
    cout << "&c:" << &c << endl;
    A a;
    if(A::s_cP == NULL)
    {
        cout << "s_cP NULL" << endl;
        return 0;
    }
    A::s_cP->Do();
    return 0;
}

结果:this C
我写的例子很短,结果很有趣。当然原本的代码不可能这么简单。原本代码中class A可以看作是一个当事件发生时接受消息的类,而class B是一个消息处理的基类,class C是具体实现消息处理的类。当A有消息来时需要把消息通知给B或C,如何通知呢,调用函数Do。既然需要调用函数Do,就需要在A里面定义一个B的对象指针,至于为什么要设置成static成员变量呢?假设不设static,在class B的构造函数内又如何获取A内的class B 指针s_cP,难道在里面再定义一个A的对象。所以这些问题都不是特别难理解的,真正让我困惑的是在class B的构造函数中,this指针赋值给A::s_cP,this指针是属于class B的,但当class A的对象a调用Do函数时,最终打印的结果是“this C”。
首先很容易理解的是,子类class C实例化时会调用本身的构造函数,同时如果你没有写父类的构造函数,在本身构造之前,它会先调用父类的无参构造函数。此时的this我认为的确还是class B的this,构造完成B获得了空间,同时也有了一个隐藏的成员变量(虚函数表)。OK,接下来调用class C的构造函数。那么这边A::s_cP没有被重新赋予this指向的空间,那么记过为什么会这样呢?按照常理不应该是B的Do函数被调用吗?
换个思路,写一个很常见的例子,B *b = new C;b->Do(),调用的是class B的Do还是class C的Do函数?我相信很多人都会认为是C,为什么呢?因为Do是虚函数,它有一个虚函数表(可以理解为一个数组),存放着类内虚函数的地址,而class C继承了class B,当new C时class C的虚函数表覆盖了B的虚函数表,因此即使b属于父类指针,当他调用Do函数时,执行的就成了class C的Do函数,这是动态绑定。在回到这个例子,在main函数里,C c操作是不是也相当于把构造时默认调用的class B的构造函数生成的虚函数表覆盖了,this的确是基类class B的this,它又把this指向的地址给了class A内的静态成员变量s_cP,用个式子表达一下,B *this = new C,s_pc = this,s_pc->Do()。So 无论把地址值给多少指针,new的是C就够了,所以调用的只能是class C的Do。
此外,在说明一些,this一定是指向这个类对象的首地址的,class C继承class B,两者指向的this指针地址是相同的,换句话说分配空间的首地址相同,唯一不同的是类类型。

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qq_26654257

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值