【C++】继承,菱形继承,虚拟继承,组合详解

news2024/11/18 11:36:26

目录

1. 继承概念与定义

1.1 概念

1.2 定义

2. 父类与子类的赋值规则

3. 继承的作用域

4. 子类的默认成员函数

5. 继承与友元

6. 继承与静态成员

7. 菱形继承

7.1 继承关系

7.2 菱形继承的问题

7.3 虚拟继承

8. 继承与组合


1. 继承概念与定义

1.1 概念

1. 继承:保持原有类特性的基础上进行扩展,增加功能,这样产生新的类(派生类),本质是类的复用。

2. 子类会继承父类的成员变量和成员函数。

class Person
{
public:
     void Print()
     {
        ...
     }

protected:
     string _name = "peter"; // 姓名
     int _age = 18;  // 年龄
};

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

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

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

1.2 定义

【格式】

【继承方式】

1. 有三种继承方式。

【继承后成员访问限定符的变化】

1. 父类私有成员继承后子类不可见不可用,无论子类类内类外。

2. 父类公有或保护成员继承后与继承方式比较,谁小就是谁,public > protected > private。

3. 父类的保护成员,类外不能访问,但是可以继承给子类类内访问。

 

2. 父类与子类的赋值规则

1. 子类可以赋值给父类/父类指针/父类引用。

2. 父类不可以赋值给子类。

3. public继承中,子类可以看作是一个特殊的父类,is-a的关系。

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

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

void Test ()
{
 Student s;
 
 Person p = s;
 Person* pp = &s; //指向子类的父类部分
 Person& rp = s; //父类部分的引用
}

 

3. 继承的作用域

1. 父类和子类都有自己的独立作用域。

2. 父类和子类允许有同名成员,默认访问子类的,因为隐藏了父类的同名成员,想访问父类的同名成员使用基类::基类成员显示访问。

class Person
{
protected :
     int _num = 111;   
};

class Student : public Person
{
public:
     void Print()
     {
         cout << Person::_num << endl; //显示访问父类
         cout << _num << endl; //默认访问子类同名
     }

protected:
     int _num = 999; 
};

【注意】

1. 重载必须是相同作用域。

2. 成员函数的函数名相同就会构成隐藏。

class A
{
public:
     void fun()
     {
         cout << "func()" << endl;
     }
};

class B : public A
{
public:
     void fun(int i)
     {
         A::fun();
         cout << "func(int i)->" <<i<<endl;
     }
};

 

4. 子类的默认成员函数

1. 我们把子类的成员变量看作三部分,内置类型,自定义类型,继承的父类成员变量,把继承的父类看作一个整体。

2. 派生类的构造函数必须调用基类的构造函数初始化基类的那一部分成员,子类变量的构造自己实现。

3. 子类的拷贝构造同理,派生类的拷贝构造函数必须调用基类的拷贝构造完成基类的拷贝初始化,自己实现子类的拷贝构造。

4. 派生类的operator=必须要调用基类的operator=完成基类的复制。

5. 子类的析构函数结束后会自动调用父类的析构函数,析构的顺序是先子后父,因为先父后子的子可能会访问父。

//父类
class Person
{
public:
     //父类构造
     Person(const char* name = "peter")
     : _name(name)
     {
         cout<<"Person()" <<endl;
     }
    
     //父类拷贝构造  
     Person(const Person& p)
     : _name(p._name)
     {
        cout<<"Person(const Person& p)" <<endl;
     }
    
     //父类赋值重载
     Person& operator=(const Person& p )
     {
        cout<<"Person operator=(const Person& p)"<< endl;
        if (this != &p)
            _name = p ._name;
        
        return *this ;
     }
        
     //父类析构    
     ~Person()
     {
         cout<<"~Person()" <<endl;
     }

protected:
     string _name; // 姓名
};

//子类
class Student : public Person
{
public:
     //子类构造
     Student(const char* name, int num)
     :Person(name) //父类部分的构造交给父类构造
     ,_num(num)
     {
         cout<<"Student()" <<endl;
     }
 
     //子类拷贝
     Student(const Student& s)
     :Person(s) //父类部分的拷贝交给父类拷贝
     ,_num(s._num)
     {
         cout<<"Student(const Student& s)" <<endl ;
     }
     
     //子类赋值重载   
     Student& operator=(const Student& s)
     {
         cout<<"Student& operator= (const Student& s)"<< endl;
         if (this != &s)
         {
             Person::operator=(s); //这里显示调用因为构成了隐藏
             _num = s._num;
         }
         return *this ;
     } 
     
     //子类析构   
     ~Student() 
     {
         cout<<"~Student()" <<endl;
     }

protected:
     int _num ; //学号
};

 

5. 继承与友元

1. 友元关系不能继承,也就是说基类友元不能访问子类私有和保护成员。

 

6. 继承与静态成员

1. 基类定义了static静态成员,则整个继承体系里面只有一个这样的成员。无论派生出多少个子 类,都只有一个static成员实例。

2. 父类的静态成员不属于某个对象,属于整个类,继承的子类也有使用权。

 

7. 菱形继承

7.1 继承关系

【单继承】

一个子类只有一个直接父类时称这个继承关系为单继承

【多继承】

一个子类有两个或以上直接父类时称这个继承关系为多继承

【菱形继承】

菱形继承是多继承的一种特殊情况。

7.2 菱形继承的问题

菱形继承的问题:从下面的对象成员模型构造,可以看出菱形继承有数据冗余和二义性的问题。

在Assistant的对象中Person成员会有两份。

1. 两个_name会造成数据二义性,这个可以显示调用解决。

2. 数据冗余无法解决。

class Person
{
public :
     string _name ; // 姓名
};

class Student : public Person
{
protected :
     int _num ; //学号
};

class Teacher : public Person
{
protected :
     int _id ; // 职工编号
};

class Assistant : public Student, public Teacher
{
protected :
     string _majorCourse ; // 主修课程
};

7.3 虚拟继承

1. 虚拟继承可以解决菱形继承的二义性和数据冗余的问题。

2. vircual关键字要加在继承冗余的类的位置,比如这里冗余的是person类,那么谁继承person就要用虚拟继承。

class Person
{
public :
     string _name ; // 姓名
};

class Student : virtual public Person
{
protected :
     int _num ; //学号
};

class Teacher : virtual public Person
{
protected :
     int _id ; // 职工编号
};

class Assistant : public Student, public Teacher
{
protected :
     string _majorCourse ; // 主修课程
};

【原理】

1. 冗余的变量会被放到最下面。

2. 原本的位置变成一个地址,这个地址指向一张表(虚基表),表里有这个冗余变量的偏移量,通过偏移量可以找到它。

8. 继承与组合

1. public继承是一种is-a的关系。也就是说每个派生类对象都是一个基类对象。

2. 组合是一种has-a的关系。假设B组合了A,每个B对象中都有一个A对象。

3. 继承允许你根据基类的实现来定义派生类的实现。这种通过生成派生类的复用通常被称为白箱复用(white-box reuse)。在继承方式中,基类的内部细节对子类可见。继承一定程度破坏了基类的封装,基类的改变,对派生类有很大的影响。派生类和基类间的依赖关系很强,耦合度高。

4. 对象组合是类继承之外的另一种复用选择。新的更复杂的功能可以通过组装或组合对象来获得。对象组合要求被组合的对象具有良好定义的接口。这种复用风格被称为黑箱复(black-box reuse),因为对象的内部细节是不可见的。组合类之间没有很强的依赖关系,耦合度低。

//组合
class A
{
public:
    int _a;
}

class B 
{
private:
    A a;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2176102.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于SpringCloud的微服务架构下安全开发运维准则

为什么要进行安全设计 微服务架构进行安全设计的原因主要包括以下几点&#xff1a; 提高数据保护&#xff1a;微服务架构中&#xff0c;服务间通信频繁&#xff0c;涉及到大量敏感数据的交换。安全设计可以确保数据在传输和存储过程中的安全性&#xff0c;防止数据泄露和篡改。…

物联网迎来下半场,国产 IoTOS 打造企业级智能硬件云服务平台

如有需求&#xff0c;文末联系小编 氦氪云 IoTOS 是一套先进的企业级物联网解决方案平台&#xff0c;为万物互联提供可靠安全稳定的终端接入、协议适配、消息路由、数据存储和分析、应用使能等核心功能。面向物联网领域中的终端设备商、系统集成商、应用服务商、能力提供商等&a…

定积分中静水压力问题

静水压力与定积分 静水压力问题是定积分在物理学中的一个重要应用。它利用积分的思想&#xff0c;将一个复杂的、连续变化的压力分布问题转化为一系列微小压力单元的累加&#xff0c;最终求出总压力。 基本原理&#xff1a; 静水压力是指静止液体对浸在其中的物体表面所施加…

BUG——IMX6ULL编译正点原子Linux内核报错

最初编译的是正点原子改过的Linux内核&#xff0c;可能是版本问题&#xff0c;一直报错&#xff0c;无法成功编译。然后换成NXP官方Linux内核6.6版本&#xff0c;初始编译虽然也报各种错&#xff0c;但都是缺少库或相关工具&#xff0c;全部安装后就可以成功编译出镜像了&#…

【RocketMQ】MQ与RocketMQ介绍

&#x1f3af; 导读&#xff1a;本文介绍了消息队列&#xff08;MQ&#xff09;的基本概念及其在分布式系统中的作用&#xff0c;包括实现异步通信、削峰限流和应用解耦等方面的优势&#xff0c;并对ActiveMQ、RabbitMQ、RocketMQ及Kafka四种MQ产品进行了对比分析&#xff0c;涵…

【Canvas与诗词】秋夕.杜牧(银烛秋光冷画屏......)

【成图】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>金六边形外圈绿色底录杜牧秋夕诗</title><style type"…

Unity实战案例全解析:RTS游戏的框选和阵型功能(1) 基础要素

本案例来源于unity唐老狮&#xff0c;有兴趣的小伙伴可以去泰克在线观看该课程 【唐老狮】Unity实现 即时战略游戏 阵型功能 - 泰课在线 -- 志存高远&#xff0c;稳如泰山 - 国内专业的在线学习平台|Unity3d培训|Unity教程|Unity教程 Unreal 虚幻 AR|移动开发|美术CG - Powered…

【CTF Web】Pikachu 反射型xss(get) Writeup(反射型XSS+GET请求)

XSS&#xff08;跨站脚本&#xff09;概述 Cross-Site Scripting 简称为“CSS”&#xff0c;为避免与前端叠成样式表的缩写"CSS"冲突&#xff0c;故又称XSS。一般XSS可以分为如下几种常见类型&#xff1a; 1.反射性XSS; 2.存储型XSS; 3.DOM型XSS; XSS漏洞一直被评估…

Java基于easyExcel的自定义表格格式

这里用的到easyExcel版本为3.3.4 <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.3.4</version></dependency> 效果 代码部分 package com.tianyu.test;import com.alibaba.exc…

全网最适合入门的面向对象编程教程:54 Python字符串与序列化-字符串格式化与format方法

全网最适合入门的面向对象编程教程&#xff1a;54 Python 字符串与序列化-字符串格式化与 format 方法 摘要&#xff1a; 在 Python 中&#xff0c;字符串格式化是将变量插入到字符串中的一种方式&#xff0c;Python 提供了多种字符串格式化的方法&#xff0c;包括旧式的 % 格…

BFS之最短路径模型

当一个图的每个边的权重都一样的时候&#xff0c;会有一个最短路径模型。不需要考虑边的影响。 1076. 迷宫问题 - AcWing题库 #include<iostream> #include<queue> #include<utility> #include<algorithm> #include<stack> using namespace std…

C语言课程设计题目七:学生成绩管理系统设计

题目七&#xff1a;学生成绩管理系统设计 学生成绩信息包括&#xff1a;学期&#xff0c;学号&#xff0c;班别&#xff0c;姓名&#xff0c;四门课程成绩(语文、数学、英语和计算机)等。 主要功能&#xff1a; 能按学期、按班级完成对学生成绩的录入、修改。能按班级统计学生…

力扣最热一百题——颜色分类

目录 题目链接&#xff1a;75. 颜色分类 - 力扣&#xff08;LeetCode&#xff09; 题目描述 示例 提示&#xff1a; 解法一&#xff1a;不要脸用sort Java写法&#xff1a; 运行时间 解法二&#xff1a;O1指针 Java写法&#xff1a; 重点 运行时间 C写法&#xff1a;…

Python库matplotlib之二

Python库matplotlib之二 figureAxessubplot figure matplotlib.pyplot.figure(numNone, figsizeNone, dpiNone, facecolorNone, edgecolorNone, frameonTrue, FigureClass<class ‘matplotlib.figure.Figure’>, clearFalse, **kwargs) num&#xff0c;int 或 str 或 fi…

Starfyre:一款使用纯 Python 创建响应式前端应用的 Python Web 框架

Starfyre 是一款基于 WebAssembly (WASM) 的 Python Web 框架&#xff0c;它允许你使用纯 Python 创建响应式前端应用。这意味着你可以轻松地构建交互式、实时应用程序&#xff0c;无需繁琐的 JavaScript 代码。Starfyre 基于 Pyscript 实现客户端功能&#xff0c;并通过 pyxid…

【每天学个新注解】Day 9 Lombok注解简解(八)—@Synchronized、@Locked

Synchronized 通过锁代码块的方式实现同步锁。 当synchronized修饰类属性时&#xff0c;通常用于定义同步代码块&#xff0c;此时需要指定一个锁对象。这个锁对象通常是类的某个私有静态成员变量&#xff0c;因为类属性是静态的&#xff0c;所以锁也应该是静态的&#xff0c;以…

【Python】YOLO牛刀小试:快速实现视频物体检测

YOLO牛刀小试&#xff1a;快速实现视频物体检测 在深度学习的众多应用中&#xff0c;物体检测是一个热门且重要的领域。YOLO&#xff08;You Only Look Once&#xff09;系列模型以其快速和高效的特点&#xff0c;成为了物体检测的首选之一。本文将介绍如何使用YOLOv8模型进行…

二叉搜索树的介绍、模拟实现二叉搜索树、leetcode---根据二叉树创建字符串、leetcode---二叉树的最近公共祖先等的介绍

文章目录 前言一、二叉搜索树的介绍二、模拟实现二叉搜索树三、leetcode---根据二叉树创建字符串四、leetcode---二叉树的最近公共祖先总结 前言 二叉搜索树的介绍、模拟实现二叉搜索树、leetcode—根据二叉树创建字符串、leetcode—二叉树的最近公共祖先等的介绍 一、二叉搜索…

57 长短期记忆网络(LSTM)_by《李沐:动手学深度学习v2》pytorch版

系列文章目录 文章目录 系列文章目录长短期记忆网络&#xff08;LSTM&#xff09;门控记忆元输入门、忘记门和输出门候选记忆元 (相当于RNN中计算 H t H_t Ht​)记忆元隐状态 从零开始实现初始化模型参数定义模型训练和预测 简洁实现小结练习 长短期记忆网络&#xff08;LSTM&a…

0基础学习CSS(六)字体

CSS 字体 CSS字体属性定义字体&#xff0c;加粗&#xff0c;大小&#xff0c;文字样式。 serif和sans-serif字体之间的区别 在计算机屏幕上&#xff0c;sans-serif字体被认为是比serif字体容易阅读 CSS字型 在CSS中&#xff0c;有两种类型的字体系列名称&#xff1a; 通用字体…