news 2026/4/20 2:46:32

【C++初阶】继承(一)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【C++初阶】继承(一)


🎬 博主名称:键盘敲碎了雾霭

🔥 个人专栏: 《C语言》《数据结构》 《C++》《Matlab》 《Python》
⛺️指尖敲代码,雾霭皆可破

文章目录

  • 一、继承的定义
    • 1.1 概念
    • 1.2 父类访问变化
    • 1.3 继承类模版
  • 二、赋值兼容转化
  • 三、继承中的作用域
  • 四、派生类的默认成员函数
    • 4.1 构造函数
    • 4.2 拷贝构造
    • 4.3 赋值重载
    • 4.4 析构
    • 4.5 总结
  • 文章结语

一、继承的定义

1.1 概念

继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它允许我们在保持原有类特性的基础上进行扩展,增加方法(成员函数)和属性(成员变量),这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。以前我们接触的函数层次的复用,继承是类设计层次的复用
定义格式:Person是基类,也称作父类。Student是派生类,也称作子类

通过具体实例来理解:

#include<iostream>#include<string>usingnamespacestd;classParent{public:voididentity(){cout<<"identity()"<<_name<<endl;}protected:string _name="张三";};classStudent:publicParent{public:voidstudy(){cout<<"study()"<<endl;}protected:string id;};classTeacher:publicParent{public:voidteach(){cout<<"teach()"<<endl;}protected:string _title;};intmain(){Student s1;Teacher t1;s1.identity();return0;}

1.2 父类访问变化

由于不同的继承方式,继承基类成员访问方式的变化,原来的成员变量会变成另外一种(private除外)

类成员/继承方式public继承protected继承private继承
基类的public成员派生类的public成员派生类的protected成员派生类的private成员
基类的protected成员派生类的protected成员派生类的protected成员派生类的private成员
基类的private成员在派生类中不可见在派生类中不可见在派生类中不可见
  • 基类private成员在派生类中无论以什么方式继承都是不可见的。这里的不可见是指基类的私有成员还是被继承到了派生类对象中,但是语法上限制派生类对象不管在类里面还是类外面都不能去访问它。
  • 基类private成员在派生类中是不能被访问,如果基类成员不想在类外直接被访问,但需要在派生类中能访问,就定义为protected。可以看出保护成员限定符是因继承才出现的。
  • 实际上面的表格我们进行一下总结会发现,基类的私有成员在派生类都是不可见。基类的其他成员在派生类的访问方式==Min(成员在基类的访问限定符,继承方式),public>protected>private.
  • 使用关键字class时默认的继承方式是private,使用struct时默认的继承方式是public,不过最好显示的写出继承方式。
  • 在实际运用中一般使用都是public继承,几乎很少使用protetced/private继承,也不提倡使用
    protetced/private继承,因为protetced/private继承下来的成员都只能在派生类的类里面使用,实际中扩展维护性不强。

1.3 继承类模版

基类是类模板时,需要指定一下类域,因为模版是按需实例化,当成员函数未实例化时,编译器找不到基类成员函数

#defineContainvectornamespaceA{template<classT>classstack:publicContain<T>{public:voidpush(constT&x){Contain<T>::push_back(x);}voidpop(){Contain<T>::pop_back();}constT&top(){returnContain<T>::back();}size_tsize(){returnContain<T>::size();}boolempty(){returnContain<T>::empty();}};}intmain(){A::stack<int>st;}

二、赋值兼容转化

public继承的派生类对象 可以赋值给 基类的指针/基类的引用。有个形象的说法叫切片或者切割
注意:
基类对象不能赋值给派生类对象(子类有的,父类没有,强转也是不可以的)
基类的指针或者引用可以通过强制类型转换赋值给派生类的指针或者引用。但是必须是基类的指针是指向派生类对象时才是安全的。

Student s;Parent&temp=s;//不是隐式类型转化,如果是的话,会产生临时变量,不支持引用Parent*temp1=&s;Parent temp2=s;

三、继承中的作用域

  • 在继承体系中基类和派生类都有独立的作用域
  • 派生类和基类中有同名成员,派生类成员将屏蔽基类对同名成员的直接访问,这种情况叫隐藏。
    在派生类成员函数中,可以使用基类::基类成员显示访问
classParent{protected:int_num=10;};classStudent:publicParent{public:voidFuc(){cout<<_num<<endl;//优先访问当前作用域的cout<<Parent::_num<<endl;}protected:int_num=100;};intmain(){Student st;st.Fuc();}
  • 需要注意的是如果是成员函数的隐藏,只需要函数名相同就构成隐藏。不是重载(不在同一作用域)
classParent{public:voidFuc1(){cout<<"haha"<<endl;}};classStudent:publicParent{public:voidFuc1(inti){cout<<"hehe"<<endl;}};intmain(){Student st;st.Parent::Fuc1();}
  • 注意在实际中在继承体系里面最好不要定义同名的成员。

四、派生类的默认成员函数

关于默认成员函数,不熟悉的小伙伴可以通过这篇文章来了解下
【C++初阶】类和对象(二):默认成员函数详解与日期类完整实现

4.1 构造函数

默认生成的构造函数的行为

  • 内置类型->不确定
  • 自定义类型->调用默认构造
  • 继承父类成员看做一个整体对象,要求调用父类的默认构造

派生类的构造函数必须调基类的构造函数初始化基类的那一部分成员。如果基类没有默认的构造函数,则必须在派生类构造函数的初始化列表阶段显示调用
具体实例:

classParent{public:Parent(string name):_name(name){}protected:string _name;};classStudent:publicParent{public:Student(string id,string name,intscore):_id(id)//,_name(name),Parent(name),_score(score){}protected:string _id;int_score=100;};intmain(){Students("123","lishi",60);return0;}

4.2 拷贝构造

默认生成的拷贝构造函数的行为

  • 内置类型->值
  • 自定义类型->调用默认构造拷贝
  • 继承父类成员看做一个整体对象,要求调用父类的默认拷贝构造

与赋值重载、析构类似,当有资源释放时,才需要写拷贝构造
派生类的拷构造函数必须调基类的拷贝构造完成基类的拷贝初始化(如果不调用父类的拷贝构造,会调用默认构造,不满足需求)。

classParent{public:Parent(string name):_name(name){}Parent(constParent&s){cout<<"Parent(Parent& s)"<<endl;}protected:string _name;};classStudent:publicParent{public:Student(string id,string name,intscore):_id(id)//,_name(name),Parent(name),_score(score){}Student(constStudent&s):_id(s._id),_score(s._score),Parent(s){}protected:string _id;int_score=100;//int* _ptr =new[20];};intmain(){Students("123","lishi",60);Students1(s);return0;}

从声明的角度,初始化列表会先调父类的拷贝构造(按内存的顺序),父类在前面

4.3 赋值重载

严格说student赋值重载默认生成的就够用了如果有需要深拷贝的资源,才需要自己实现

派类的operator=必须要调基类的operator=完成基类的复制。需要注意的是派类的operator=隐藏了基类的operator=,所以显示调基类的operator=,需要指定基类作域

classParent{public:Parent(string name):_name(name){}Parent(constParent&s){cout<<"Parent(Parent& s)"<<endl;}Parent&operator=(constParent&s){cout<<"Person operator=(const Person& p)"<<endl;if(this!=&s)_name=s._name;return*this;}protected:string _name;};classStudent:publicParent{public:Student(string id,string name,intscore):_id(id)//,_name(name),Parent(name),_score(score){}Student(constStudent&s):_id(s._id),_score(s._score),Parent(s){}Student&operator=(constStudent&s){if(this!=&s){_id=s._id;_score=s._score;Parent::operator=(s);return*this;}}protected:string _id;int_score=100;//int* _ptr =new[20];};intmain(){Students("123","lishi",60);Students1(s);Students2(s);s1=s2;return0;}

4.4 析构

如果没有资源申请,不需要在子类显示写析构函数,父类会自动调析构函数
生类的析构函数会在被调完成后自动调用基类的析构函数清理基类成员。因为这样才能保证派生类对象先清理派生类成员再清理基类成员的顺序
派生类对象初始化先调用基类构造再调派生类构造。
派生类对象析构清理先调用派生类析构再调基类的析构。

补充:子类的析构和父类的析构构成隐藏关系,编译器会对析构函数名进行特殊处理,都处理成destructor()

4.5 总结

构造阶段 (创建对象时),先调用基类构造函数,再调用派生类构造函数。
析构阶段 (销毁对象时),先调用派生类析构函数,再调用基类析构函数

文章结语

感谢你读到这里~我是「键盘敲碎了雾霭」,愿这篇文字帮你敲开了技术里的小迷雾 💻

如果内容对你有一点点帮助,不妨给个暖心三连吧👇
👍点赞| ❤️收藏| ⭐关注
(听说三连的小伙伴,代码一次编译过,bug绕着走~)

你的支持,就是我继续敲碎技术雾霭的最大动力 🚀

🐶 小彩蛋:

/^ ^\ / 0 0 \ V\ Y /V / - \ / | V__) ||

摸一摸毛茸茸的小狗,赶走所有疲惫和bug~我们下篇见 ✨

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/20 2:45:31

今天爬山去了 , 所以就刷了一道力扣

爬的的焦作的云台山 , 人超多 , 超多 , 超多 , 真的多 , 好多帅哥哥 , 和漂亮小姐姐 . 挺值得 , 门票 60 夯爆了. 回到学校后实在没力气学习了 , 就只刷了一道力扣简单题. 晚上 自己搞了: 观看技术直播 AI 大模型应用开发 Python 结语 人生的意义很简单 : 就是每天都开开…

作者头像 李华
网站建设 2026/4/20 2:42:49

如何高效优化系统性能:联想拯救者工具箱终极硬件管理指南

如何高效优化系统性能&#xff1a;联想拯救者工具箱终极硬件管理指南 【免费下载链接】LenovoLegionToolkit Lightweight Lenovo Vantage and Hotkeys replacement for Lenovo Legion laptops. 项目地址: https://gitcode.com/gh_mirrors/le/LenovoLegionToolkit 联想拯…

作者头像 李华
网站建设 2026/4/20 2:35:28

你的百度网盘下载为什么这么慢?秘密武器在这里!

你的百度网盘下载为什么这么慢&#xff1f;秘密武器在这里&#xff01; 【免费下载链接】baidu-wangpan-parse 获取百度网盘分享文件的下载地址 项目地址: https://gitcode.com/gh_mirrors/ba/baidu-wangpan-parse 你是否曾经面对百度网盘的下载界面&#xff0c;看着那缓…

作者头像 李华