我的编程空间,编程开发者的网络收藏夹
学习永远不晚

一文搞懂C++中继承的概念与使用

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

一文搞懂C++中继承的概念与使用

前言

我们都知道面向对象语言的三大特点是:**封装,继承,多态。**之前在类和对象部分,我们提到了C++中的封装,那么今天呢,我们来学习一下C++中的继承。

继承概念及定义

继承概念

继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。以前我们接触的复用都是函数复用,继承是类设计层次的复用

看概念是一件很让人疑惑的东西,接下来我就来举个例子来看看继承具体是什么东西

首先我们定义两个类,一个Student类,一个Teacher类,二者都有年龄和姓名,学生有学号,老师有工号。

class Student
{
private:
    int _age;     //年龄
    string _name; //姓名
    int _stuid;   //学号
};

class Teacher
{
private:
    int _age;     //年龄
    string _name; //姓名
    int _jobid;   //工号
};

我们发现这两个类有一些重复的地方,比如年龄和姓名,这二者是他们的成员,此时代码就产生了冗余。那么我们可不可以像个方法去复用这两个成员呢?继承此时就可以发挥它的重大作用。

我们将他们重复的地方提取出来,重新定义一个Person类。而Student类和Teacher类将Person类继承下来,此时我们就实现了代码的复用。

class Person
{
protected:
	int _age;     //年龄
	string _name; //姓名
};

class Student : public Person
{
private:
	int _stuid; //学号
};

class Teacher : public Person
{
private:
	int _jobid; //工号
};

我们首先分别用Student和Teacher类来创建两个对象,来看看对象里面有什么。

int main()
{
    Teacher t;
    Student s;
    return 0;
}

此时我们可以看到我们创建的两个对象里面都含有从Person类中继承过来的 age 和 name 两个成员。

所以继承实际上是一个代码的复用,我们可以借用已完成的类的代码来完善我们需要创造的新类。

继承定义

以我们刚刚创建的Student类来举例:我们看到Person是父类,也称作基类。Student是子类,也称作派生类。

继承方式

我们在类和对象的时候介绍了三种访问限定符:public(公有),protected(保护)和private(私有)。访问限定符限定了我们在类外如何去访问类中的成员。

在继承中我们一样使用这三种限定符来限定子类该如何去访问父类的的成员,下面有一张表来表示他们的关系。

类成员\继承方式public继承protected继承private继承
父类的public成员派生类的public成员派生类的protected成员派生类的private成员
父类的protected成员派生类的protected成员派生类的protected成员派生类的private成员
父类的private成员在派生类中不可见在派生类中不可见在派生类中不可见

首先解释一下在派生类中不可见是什么意思,就如同我们在类外无法直接去修改类中的private成员一样,我们在子类中也无法直接修改父类的private成员。

如何简洁的去记这个表呢?在C++中权限的关系:public > protected > private。在继承的时候呢,父类成员的权限取的是:父类成员原本权限和继承方式中较小的那个。

比如父类的A成员原本权限为public,而子类的继承方式为private。此时A成员相对子类来说就为private成员

父类和子类对象赋值转换

子类的对象可以赋值给 父类的对象/父类的指针/父类的应用,那么是如何进行赋值的呢?形象一点来说就是切片,将子类中父类的部分切割父类。

但我们无法反过来,将父类对象赋值给子类对象。

继承中的作用域

在继承体系中父类和子类都有独立的作用域,如果子类和父类中有同名的成员,子类成员将屏蔽对父类成员的直接访问,这种情况叫隐藏,也叫重定义。

下面还是用我们的Person类和Student类来举个栗子,我们分别在Person类和Student类中加入一个print函数,通过打印内容来区分调用的为哪一print函数。

class Person
{
protected:
    int _age;
    string _name;

public:
    void print()
    {
        cout << "Person"<< endl;
    }
};

class Student : public Person
{
private:
    int _stuid; //学号
    public:
    void print()
    {
        cout << "Student" << endl;
    }
};

接下来我们创建一个对象然后来试一下结果。

int main()
{
    Student s;
    s.print();
    return 0;
}

我们可以看到我们调用的为Student中的print函数。此时子类的print函数已经对父类的print函数进行了重定义。重定义不代表子类无法去调用父类的同名函数,只是不那么直接而已。使用下面这种方法我们就可以调用父类中的同名函数。

int main()
{
    Student s;
    s.Person::print();
    return 0;
}

通过指定类域,我们就可以去调用父类的print函数。但在实际中最好不要去定义同名函数以免带来问题。

派生类的默认成员函数

首先我们来回顾一下有哪几个默认成员函数。

那么在子类中,这些默认成员函数是怎么生成的呢?

1.子类的构造函数必须调用父类的构造函数初始化父类的那一部分成员。如果父类没有默认的构造函数,则必须在派生类构造函数的初始化列表中显式调用。还是用我们的Person类和Student类举例。

情况一:有默认构造函数

class Person
{
protected:
    int _age;
    string _name;

public:
    Person()
    {
        cout << "Person" << endl; //调用就打印
    }
};

class Student : public Person
{
private:
    int _stuid; //学号
public:
    Student()
    {
        cout << "Student" << endl; //调用就打印
    }
};

int main()
{
    Student s;
    return 0;
}

情况二:无默认构造函数

class Person
{
protected:
    int _age;
    string _name;

public:
    Person(int age, string name)
    {
        cout << "Person" << endl;
    }
};

class Student : public Person
{
private:
    int _stuid; //学号
public:
    Student()
        : Person(19, "wanku") //无默认构造,此时我们需要在初始化列表中初始化
    {
        cout << "Student" << endl;
    }
};

int main()
{
    Student s;
    return 0;
}

int main()
{
    Student s;
    return 0;
}

2.子类的拷贝构造函数必须调用父类的拷贝构造完成父类的拷贝初始化化。

class Person
{
protected:
    int _age;
    string _name;

public:
    Person(int age = 10, string name = "wanku")
    {
        cout << "Person" << endl;
    }

    Person(const Person &p)
        : _age(p._age), _name(p._name)
    {}
};

class Student : public Person
{
private:
    int _stuid; //学号
public:
    Student()
    {
        cout << "Student" << endl;
    }

    Student(const Student &s)
        : Person(s) , _stuid(s._stuid)
    {}
};

有些朋友可能会疑惑,在Person类中的拷贝构造函数参数明明是Person类,为什么我们的Student类可以传过去呢?那是因为我们刚刚讲的切片原理,当我们把子类对象传过去时,编译器会进行切分,然后再传给父类。

3.派生类的operator=必须要调用基类的operator=完成基类的复制。(原理和拷贝构造大体相似,值得注意的是:当我们在子类直接想去调用父类的operator= 时,会发生重定义,使用时记得加上父类的作用域)

4.在继承中一个对象的历程如下:父类的构造函数 –> 子类的构造函数 –> 子类的析构函数 –> 父类的析构函数。这个过程相当于把这些行为存在一个栈中,然后再把行为从栈中拿出来一般

派生类的友元与静态成员

父类的友元不是子类的友元。(你爸爸的朋友不一定是你的朋友)

父类中有一个静态成员,那么子类和父类共用一个静态成员。(静态成员并不存在对象中,只开辟一个空间,所以只能共用一个)

继承关系

单继承

一个子类只有一个直接父类。

多继承

一个子类有两个及以上的父类

菱形继承

多继承的一种特殊情况

以上就是一文搞懂C++中继承的概念与使用的详细内容,更多关于C++继承的资料请关注编程网其它相关文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

一文搞懂C++中继承的概念与使用

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

一文搞懂JavaScript中最难理解概念之一的闭包

闭包常常被誉为JavaScript中最难理解的概念之一,这篇文章就来带大家深入了解一下JavaScript中闭包的概念、实现与应用,需要的可以参考一下
2023-05-14

一文搞懂python中Tkinter的使用

本篇文章给大家带来了关于Python的相关知识,其中主要整理了Tkinter的相关问题,Tkinter 是使用 python 进行窗口视窗设计的模块,下面一起来看一下,希望对大家有帮助。【相关推荐:Python3视频教程 】一、前言1.1、Tkinter是什么Tkinter 是使用 python 进行窗口视窗设计的模块。Tkinter模块(“Tk 接口”)是Python的标准Tk GUI工具包的接口
2022-07-04

一文带你搞懂Vue中Vuex的使用

​ Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态。本文会通过一些简单的示例,为大家详细讲解Vuex的使用,感兴趣的小伙伴可以跟随小编一起学习一下
2022-11-13

一文搞懂Python中subprocess模块的使用

subprocess是子流程,即进程的意思,该模块可以启动一个新进程,并连接到它们的输入/输出/错误管道,从而获取返回值。本文将和大家聊聊subprocess模块的使用,需要的可以参考一下
2022-11-21

一文带你搞懂Java中Synchronized和Lock的原理与使用

这篇文章主要为大家详细介绍了Java中Synchronized和Lock的原理与使用,文中的示例代码讲解详细,对我们学习Java有一定的帮助,需要的可以参考一下
2023-05-16

详解C#中委托的概念与使用

委托这个名字取的神乎其神的,但实质是函数式编程,把函数作为参数传递给另一个参数。这篇文章主要为大家介绍一下C#中委托的概念与使用,需要的可以参考一下
2023-02-27

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录