当前位置: 首页 > news >正文

一文学会c++继承 组合

文章目录

  • 继承简介
    • 定义
    • 访问限定符和继承方式
  • ⭐基类派生类赋值转换
  • 继承的作用域
  • 派生类的默认成员函数
  • 继承与友元
  • 继承与静态成员
  • ⭐复杂的菱形继承
    • 虚拟继承
  • 组合

继承简介

继承是面向对象程序设计代码复用的重要手段,使得程序员可以在保持原类的基础上扩展,新扩展的类叫派生类体现类的层级结构,之前的重载是函数复用,继承是类的复用

定义

#include <iostream>
#include <string>
using namespace std;
class person
{
public:void print(){cout << _name << " " << _sex << " " << _age << endl;;}
protected:string _name ="Jack";string _sex ="man";int _age=18;
};
class student : public person
{
protected:int _number;
};
int main()
{person p1;student s1;p1.print();s1.print();return 0;
}

可以看到,student是派生类,public是继承方式,person是基类
派生类拥有基类的所有成员

访问限定符和继承方式

在这里插入图片描述

在这里插入图片描述
总结
1,基类的private成员,无论什么继承,派生类都不可见,但是成员还是继承到了派生类中,但是语法限制了派生类访问
2,基类的private在派生类不可见,要想突破限制,就用protected,在类外不可访问,但在派生类可访问,访问限制符protected是为继承准备的
3,观察上面表格,可以发现两个不同限定符,取范围更小的,如protected和private 取private
4,class类默认继承方式private,struct类默认public一般都写出继承方式的
5,一般都是public继承,几乎很少private/protected

⭐基类派生类赋值转换

🚩 派生类对象可以赋值基类对象/基类引用/基类指针,这个过程叫切片,意为着把派生类那块基类所有的切给基类,
🚩基类对象不能赋值给派生类
在这里插入图片描述
如图,派生可以赋值给基类,只不过 _number消失了

int main()student s2;person p2 = s2;person* pp2 = &s2;person& ppp2 = s2;student* ss2 = (student*)pp2;//这种强转可以pp2 = &p2;//student* ss2 = (student*)pp2;//这种会越界访问return 0;

继承的作用域

class person
{
public:void print(){cout << "基类" << endl;}
};
class student : public person
{
public:void print(){cout << "派生类" << endl;}
};
int main()
{student s3;s3.print();s3.student::print();s3.person::print();return 0;
}

在这里插入图片描述
1,基类和派生类都有独立的作用域
🚩2,基类与派生类成员重名时,子类调用会直接跳过父类成员,这叫隐藏,也叫重定义,或者可用 类名::成员 访问
🚩3,在一个作用域的重名叫重载两个作用域重名叫隐藏
4,继承体系最好不要定义重名成员

派生类的默认成员函数

1,派生类对象初始化先调用基类构造函数,若基类无默认构造函数,则要在初始化列表显式调用,再调用自己的构造函数
2,构造,赋值,拷贝构造都是先调基类再调子类
3,析构先调子类再基类
在这里插入图片描述

#include <iostream>
#include <string>
using namespace std;
class person
{
public:person(string name ="jack"):_name(name){cout << "person()" << endl;}person(const person& p1):_name(p1._name){cout << "person(& p1)" << endl;}person& operator=(const person& p1){cout << "operator(const person&p1)" << endl;if(this!=&p1){_name = p1._name;}return *this;}~person(){ }
protected:string _name;
};
class student : public person
{
public:student(const string name="peter", int number = 110):person(name),_number(number){cout << "student()" << endl;}student(const student& s):person(s),_number(s._number){cout << "student(student& s)" << endl;}student& operator=(const student& s){if (this != &s){person::operator= (s);_number = s._number;}cout << "operator=(const student &s)" << endl;return *this;}~student(){ }
protected:int _number;
};
int main()
{person p1("peter");student s1("jack", 11);student s2;s2 = s1;return 0;
}

在这里插入图片描述

继承与友元

友元不能继承,父类的朋友不是我的朋友
所以父类友元不能访问子类成员,除非子类也声明友元

#include <iostream>
#include <string>
using namespace std;
class student;//声明
class person {
public:friend void Display(const person& p, const student& s);
protected:string _name = "person";
};class student : public person {
public:friend void Display(const person& p, const student& s); // 子类也声明为友元student(int num = 0) : _number(num) {}
protected:int _number; 
};void Display(const person& p, const student& s) {cout << p._name << endl;cout << s._number << endl; //  现在可以访问(student 的友元)
}int main() {person p;student s(12345);Display(p, s);return 0;
}

继承与静态成员

🚩基类定义static静态成员,则整个继承体系只有一个这样的成员,无论多少派生多少子类,只有这一个静态成员

#include <iostream>
#include <string>
using namespace std;
class person
{
public:person() {++_count;}string _name;static int _count;
};
int person ::_count = 0;
class student:public person
{
public:student():person(){++_count;}
};
int main()
{student s;cout << person::_count<<endl;return 0;
}

2

⭐复杂的菱形继承

单继承:一个子类只有一个父类
在这里插入图片描述
多继承:一个子类有两个及以上的父类
在这里插入图片描述
菱形继承:多继承的一种
在这里插入图片描述
下图,可看出菱形继承数据冗余二义性问题,有两份person值
在这里插入图片描述

#include <iostream>
#include <string>
using namespace std;
class person
{
public:string _name;
};
class student :public person
{
public:string _num;
};
class teacher :public person
{
public:string _id;
};
class assistant :public student, public teacher
{
public:string _majorcourse;
};
int main()
{assistant a;//a._name = "peter";//❌不明确a.student::_name = "peter";//可以指明访问,a.teacher::_name = "jack";return 0;
}

指明访问解决了二义性,但数据冗余还是没解决,

虚拟继承

虚拟继承解决了二义性和数据冗余问题,

class person
{
public:string _name;
};
class student :virtual public person
{
public:string _num;
};
class teacher :virtual public person
{
public:string _id;
};
class assistant :virtual public student, virtual public teacher
{
public:string _majorcourse;
};

原理:
在这里插入图片描述
只存一个person,student和teacher中的person 存到assistant的地址偏移量,用时再跳过去找

注意
菱形虚拟继承底层复杂,一般不设计多继承,更不能设计菱形继承

组合

继承是 is-a关系
组合是 has-a关系

  • 继承复用 基类对子类公布了成员细节,俗称白箱复用,一定程度上破坏了封装,且基类 改动对子类影响较大,子类和基类关联性强耦合度高
  • 组合复用 被组合对象要求有良好接口,基类成员细节不可见,俗称黑箱复用不破坏封装关联性低耦合度低

实战中能用组合就用组合,耦合度低,代码便于维护,不过有些情况就适合继承多态也需要继承实现,可以用继承和组合就用组合

class car
{
protected:string _colour;string _num;
};class Benz :public car
{
public:void Drive(){cout << "奢华" << endl;}
};

继承关系

class tire
{
public:string _brand;int _size;
};
class car {string _colour;string _num;//车牌tire _t;//轮胎
};

组合关系

http://www.dtcms.com/a/320168.html

相关文章:

  • [优选算法专题一双指针——两数之和](双指针和哈希表)
  • 解决GitHub push失败-Failed to connect to github.com port 443: Timed out
  • 亚马逊卖家反馈机制变革:纯星级评级时代的合规挑战与运营重构
  • SOMGAN:用自组织映射改善GAN的模式探索能力
  • 自然语言处理×第四卷:文本特征与数据——她开始准备:每一次输入,都是为了更像你地说话
  • python selenium环境安装
  • Python自动化测试selenium指定截图文件名方法
  • MySQL 备份利器 Xtrabackup 全解析:从部署到恢复的实战指南
  • 视觉语言模型的空间推理缺陷——AI 在医学扫描中难以区分左右
  • 《CogAgent: A Visual Language Model for GUI Agents》论文精读笔记
  • Vue 3 入门教程 9 - 表单处理
  • 8、Redis的HyperLogLog、事务Multi、管道Pipeline,以及Redis7.0特性
  • DoubleTrouble靶机
  • 【R语言】重新绘制高清MaxEnt的单因素响应曲线图像
  • 最佳左前缀法则(Optimal Left-Prefix Rule)
  • 【Dijkstra】 Shortest Routes I
  • 5种将Android联系人传输到电脑的方法
  • 《C语言》函数练习题--4
  • Debain12 api方式部署redis服务
  • 【高等数学】第八章 向量代数与空间解析几何——第二节 数量积 向量积 混合积
  • 耐压击穿测试在不同行业中的具体应用有哪些差异?
  • Clock斗篷技术:助力跨境电商营销推广的智慧策略
  • 当文档包含表格时,如何结合大模型和OCR提取数据?
  • C语言指针:补充
  • Day 34:GPU训练与类的call方法
  • [特殊字符] 未来图钉式 AI 时代的智能生态布局:副脑矩阵与人机共振的系统构想
  • USB2.0 和 USB3.0 枚举对比
  • 数据标注之数据集的类型与如何标注
  • Ubuntu24.04的“errors from xkbcomp are not fatal to the X server”终极修复方案
  • 【驱动】RK3576-Debian系统使用ping报错:socket operation not permitted