c++继承 基类 派生类 虚函数

c++ 专栏收录该内容
18 篇文章 0 订阅
继承

  类和类的关系有组合、继承和代理。继承的本质就是代码复用。子类继承父类中的一些东西,父类也称为基类,子类也称为派生类。派生类继承了基类除构造函数以外的所有成员。

继承的方式

  继承方式有public(公有继承)、private(私有继承)和protected(保护继承)。基类中不同访问限定符下(public、protected、private)的成员以不同的继承方式继承,在派生类中的访问限定也不同,具体如下:在这里插入图片描述

基类的布局优先于派生类
#include<iostream>
class Base
{
 public:
    Base(int a)
       :ma(a)
    {
    }
public:
    int ma;
};
class Derive :public Base
{
public:
    Derive(int b)
       :mb(b), Base(b)
    {
    }
public:
    int mb;
};
int main()
{
    Derive(20);
    return 0;
}

  我们可以在开发人员命令提示符窗口中进入当前源文件的目录,使用cl ConsoleApplication5.cpp /d1reportSingleClassLayoutDerive来查看派生类Derive的布局如下:
在这里插入图片描述
由图可见,基类的布局优先级高于派生类。那么派生对象的构造方式是怎么样的呢?
1.调用基类的构造函数
2.调用派生类的构造函数
派生类的析构可想而知:
1.调用派生类的析构函数
2.调用基类的析构函数

虚函数

如下程序:

class Base
{
public:
    Base(int a)
       :ma(a)
    {}
    virtual void Show()
    {
       std::cout << "Base:Show  ma=" << ma << std::endl;
    }
protected:
    int ma;
};
class Derive :public Base
{
public:
    Derive(int b)
       :mb(b), Base(b)
    {
    }
    void Show()
    {
       std::cout << "Derive:Show  mb=" << mb << std::endl;
    }
protected:
    int mb;
};
int main()
{
    std::cout << "sizeof(Base):" << sizeof(Base) << std::endl;
    std::cout << "sizeof(Derive):" << sizeof(Derive) << std::endl;
    Base* pb=new Derive(20);
    std::cout << typeid(pb).name()  << std::endl;
    std::cout << typeid(*pb).name() << std::endl;

    pb->Show();
    return 0;
}

运行结果如下:
在这里插入图片描述
  上面结果说明一个基类的指针是可以指向其派生类对象的。基类中含有虚函数,那么基类布局中存在一个虚函数指针,指向虚函数表;且其派生类中与其同名同参的函数不需要加virtual也是虚函数。此时基类和派生类的布局如下:

在这里插入图片描述
在这里插入图片描述  vfptr的指针大小为4(32位机器)。因此基类字节数为8,派生类为12。vfptr指针指向的vftable(虚函数表)中,&Base_meta中存放了RTTI信息(运行时类型信息),也就是class Base,0表示偏移,&Base::Show表示虚函数的入口地址。typeid()可以动态获取类型。
  main函数中,生成了一个派生类对象。pb是一个指针类型,它的类型只和定义点有关,因此打印出来pb的类型为class Base类型;而pb是一个自定义类型,动态获取类型时,先通过指针pb解引用找到派生类对象,通过vfptr找到vftable,&Derive_meta中存放了派生类的RTTI信息,其中存放的是class Derive,因此*pb的类型是class Derive。
  pb指针调用Show()函数时,发生了动多态。首先通过指针所指向的对象找到vfptr,再找到vftable,获取到Show函数的入口地址,此时 &Derive::Show中存放的是派生类的虚函数入口地址,因此调用的是派生类中的Show()函数。

参与评论 您还未登录,请先 登录 后发表或查看评论
©️2022 CSDN 皮肤主题:黑客帝国 设计师:我叫白小胖 返回首页

打赏作者

cleverlemon

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

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

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

打赏作者

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

抵扣说明:

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

余额充值