C++ 类和对象 继承 继承的三种方式 对象模型 构造和析构的顺序

  1. 继承的语法

class 子类 : 继承方式 父类

  1. 继承的三种方式

  • 公共继承

  • 保护继承

  • 私有继承

  • 首先,对于父类A,有三种权限的内容,公共权限内容a,保护权限内容b,私有权限内容c。

  • 其次,对于子类B,也有三种方式继承父类A的内容,公共继承、保护继承、私有继承。

  • 无论是哪种继承方式,子类B只能继承父类的公共权限内容和保护权限内容,但是不能访问私有权限内容。也就是说,对于父类A中的公共权限内容a和保护权限内容b,子类B可以继承。但是父类A中的私有权限内容c,子类B是无法访问的。

  1. 公共继承

在公共继承中,父类A的公共权限和保护权限在子类B中保持不变。也就是说,父类A中,a是公有权限,b是保护权限,在子类B中,a也是公有权限,b也是保护权限。子类无法访问父类的私有权限c。

  1. 保护继承

在保护继承中,父类A的公共权限和保护权限在子类B中都变成了保护权限。也就是说,父类A中,a是公有权限,b是保护权限,在子类B中,a和b都变成了保护权限内容。子类无法访问父类的私有权限c。

  1. 私有继承

在私有继承中,父类A的公共权限和保护权限在子类B中都变成了私有权限。也就是说,父类A中,a是公有权限,b是保护权限,在子类B中,a和b都变成了私有权限内容。子类无法访问父类的私有权限c。

  1. 三种方式的实现

  1. 父类

class Base1
{
public:
    int mA;
protected:
    int mB;
private:
    int mC;
};
  1. 子类1——公共权限继承

class Son1 :public Base1
{
public:
    void func1()
    {
        mA = 55;//父类中公共权限成员 子类中仍然是公共权限
        mB = 45;//父类中保护权限成员 子类中仍然是公共权限
        //mC = 45;//父类中私有权限成员 子类无法访问
    }
};

void test1()
{
    Son1 son1;
    son1.mA = 100;//在Son1中是公共权限类内可以访问,类外都可以访问
    //son1.mB = 100;//在Son1中是保护权限,类内可以访问,类外无法访问
}
  1. 子类2——保护权限继承

class Son2 :protected Base1
{
public:
    void func()
    {
        mA = 55;//父类中公共权限成员 子类中变为保护权限
        mB = 45;//父类中保护权限成员 子类中变为保护权限
        //mC = 45;//父类中私有权限成员 子类无法访问
    }
};

void test2()
{
    Son2 s;
    //s.mA = 100;//在Son2中,mA是保护权限,类外不可以访问
    //s.mB = 100;//在Son2中,mB是保护权限,类外不可以访问
}
  1. 子类3——私有权限继承

class Son3 :private Base
{
private:
    void func()
    {
        mA = 55;//父类中公共权限成员 子类中变为私有权限
        mB = 45;//父类中保护权限成员 子类中变为私有权限
        //mC = 45;//父类中私有权限成员 子类无法访问
    }
};

class GrandSon3 :public Son3
{
public:
    void func()
    {
        //对于GrandSon3而言,其父类是Son3,Son3中mA和mB都是私有权限,类内也无法访问
        //mA = 90;
        //mB = 90;
    }
};

void test3()
{
    Son3 s;
    //s.mA = 100;//在Son3中,mA是私有权限,类外不可以访问
    //s.mB = 100;//在Son3中,mB是私有权限,类外不可以访问
}
  1. 继承的三种方式的总结:重点在于这张图

无论是哪种继承方式,子类B只能继承父类A的公共权限内容和保护权限内容,不能访问私有权限内容。其中:

  • 公共权限类内、类外都可以访问;

  • 保护权限类内可以访问,类外不可以访问;

  • 私有权限类内、类外都不可以访问。

  1. 继承中的对象模型

  1. 问题

子类可以继承父类所有共性的内容,也就是可以继承公共权限的内容。那么,从父类继承过来的成员,哪些属于子类对象中?这些公共权限的内容是否属于子类呢?

  1. 场景描述

父类中有公共权限、保护权限、私有权限的内容,子类中使用公共继承的方式继承了父类,并且具有自己特性。通过查看子类的内存大小来判断,父类中的内容属不属于子类。

#include <iostream>
using namespace std;

class Base
{
public:
    int mA;
protected:
    int mB;
private:
    int mC;//私有成员只是被隐藏了,但是还是会继承下去
};

class Son :public Base
{
public:
    int mD;
};

void test01()
{
    cout << "sizeof Son = " << sizeof(Son) << endl;
}

int main() {

    test01();

    system("pause");

    return 0;
}

由此说明,父类中所有非静态成员属性,不管是公共、保护还是私有,都会被子类继承。此外,父类中的私有属性只是被编译器隐藏了,子类无法访问,但可以继承。

  1. 查看类对象模型

使用VS自带工具-开发人员命令提示工具,再跳转到当前源文件所在路径,再输入”dir“命令。

可以看到”继承中的对象模型.cpp“这个源文件,再查看这个对象模型

  1. 再输入命令”cl /d1 reportSingleClassLayoutSon 31“,

  1. ”reportSingleClassLayout“即报告单各类布局;

  1. ”Son“是想要查看的类名,也可以换成父类;

  1. 由于我的这个文件是第31个,再Son后敲入空格,再输入31,再按一下tab键,就会自动把这个源文件的名字补全。

  1. 最后enter,就能看到第31个源文件”...继承中的对象模型“中Son这个类的分布

这个图可以看到:

  • Son这个对象模型,内存空间是16个字节大小;

  • 父类名称是Base,继承父类的属性是mA、mB、mC;

  • Son的自身属性是mD。

  1. 总结:

  1. 子类中继承父类所有非静态成员属性,包括公共、保护、私有成员属性;

  1. 私有成员属性也继承了,只是被编译器隐藏,无法访问;

  1. 查看类对象模型的方法,利用VS自带工具-开发人员命令提示工具,定位到当前CPP文件的盘符

然后输入: cl /d1 reportSingleClassLayout查看的类名 所属文件名。

  1. 继承中构造和析构顺序

  1. 问题:

子类继承父类后,当创建子类对象,也会调用父类的构造函数。那么,父类和子类的构造和析构顺序是谁先谁后

  1. 整体实现

#include <iostream>
using namespace std;

class Base
{
public:
    Base()
    {
        cout << "Base的构造函数" << endl;
    }
    ~Base()
    {
        cout << "Base的析构函数" << endl;
    }
};

class Son :public Base
{
public:
    Son()
    {
        cout << "Son的构造函数" << endl;
    }
    ~Son()
    {
        cout << "Son的析构函数" << endl;
    }
};

void test1()
{
    //Base b;//对象创建在栈上,调用父类Base的构造和析构
    Son s;
}

int main() {

    test1();

    system("pause");

    return 0;
}

上图可以说明:

  • 创建子类Son对象s时,也会创建父类Base对象;

  • 先有父类构造函数,再有子类构造函数,因为子类继承了父类,所有得先有父类,才有子类,子类才能继承;

  • 先是子类析构函数,再是父类析构函数。

  1. 总结:

继承中,先调用父类构造函数,再调用子类构造函数,析构顺序与构造相反。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值