【QT/C++】实例理解类间的六大关系之泛化关系(Generalization)

在前面章节一文完美概括UML类图及其符号(超详细介绍)中已经对泛化关系的概念进行了总结,本文我将用实际案例来进一步理解泛化关系,以便应对未来的考试或面试!

(关注不迷路哈!!!)


文章目录

  • 【QT/C++】实例理解类间的六大关系之泛化关系(Generalization)
    • 前言 📊
    • 一、核心概念 🔍
    • 二、继承类型对比表 🔒
    • 三、代码示例与多态实现 ⚙️
      • 1. 代码实现逻辑
      • 2. 完整代码展示
      • 3. 代码实现框架
      • 4. 代码交互流程
    • 四、泛化关系的优缺点与最佳实践 💎
    • 五、面试常见问题及回答 🚀
      • 1. 问:何时使用继承?何时用组合?✅
      • 2. 问:为什么父类需要虚析构函数(virtual)?✅
      • 3. 问:多重继承会导致什么问题,如何解决?✅
      • 4. 问:如何设计图形系统且支持多态绘制?✅
    • 总结 🛠️


前言 📊

泛化关系

// 基类(抽象) // 数据库Database
class Database {
public:virtual void connect() = 0;  // 纯虚函数 // 连接数据库
};// 派生类(实现)// MySQL是数据库Database
class MySQL : public Database {
public:void connect() override {cout << "Connecting to MySQL..." << endl;}
};// 派生类(实现)// PostgreSQL是数据库Database
class PostgreSQL: public Database {
public:void connect() override {cout << "Connecting to PostgreSQL..." << endl;}
};

一、核心概念 🔍

父类定义通用接口,子类实现具体行为

特性说明
本质继承机制(父子类之间的"is-a"关系)
设计原则子类继承父类属性和方法,并可扩展新功能
多态基础父类指针/引用可指向子类对象,实现运行时绑定
UML类图表示子类 ————▷ 父类(实线 + 空心三角箭头)
代码关键字C++ 代码: class Sub : public Base

二、继承类型对比表 🔒

继承方式基类成员访问权限变化适用场景耦合度
public基类public→子类public,基类protected→子类protected严格"is-a"关系(如Dog is Animal
protected基类public/protected→子类protected限制外部访问,保留内部复用
private基类public/protected→子类private“以…方式实现”(非"is-a")

📝 关键规则:基类private成员在子类中始终不可见(存在但无法访问)。


三、代码示例与多态实现 ⚙️

1. 代码实现逻辑

代码实现逻辑

2. 完整代码展示

#include <iostream>
using namespace std;// 基类(抽象接口)
class Database {
public:virtual void connect() = 0;  // 纯虚函数,父类定义 virtual 接口方法virtual ~Database() = default; // ✅ 虚析构函数(避免资源泄漏),基类析构函数必须为 virtual,否则子类资源泄漏
};// 子类实现
class MySQL : public Database {  // public继承
public:void connect() override { // 子类用 override 显式重写(C++11及以上)cout << "MySQL: 连接成功" << endl;}
};class PostgreSQL : public Database {
public:void connect() override { // 子类用 override 显式重写(C++11及以上)cout << "PostgreSQL: 连接成功" << endl;}
};// 多态调用
void connectDatabase(Database* db) {db->connect();  // 运行时绑定具体实现
}int main() {Database* db1 = new MySQL(); // 父类指针指向子类对象connectDatabase(db1);  // 输出: MySQL: 连接成功Database* db2 = new PostgreSQL(); // 父类指针指向子类对象connectDatabase(db2);  // 输出: PostgreSQL: 连接成功delete db1;delete db2;return 0;
}

3. 代码实现框架

代码实现框架

4. 代码交互流程

代码交互流程


四、泛化关系的优缺点与最佳实践 💎

维度优点缺点最佳实践
代码复用减少冗余代码,子类复用父类逻辑父类变更可能破坏子类功能(高耦合)优先用组合(has-a)替代继承
多态支持运行时动态绑定,扩展性强虚函数调用有性能开销基类析构函数必须为virtual
设计易于表达层次关系(如动物→猫/狗)多重继承导致菱形问题(需虚继承解决)避免超过3层继承深度

泛化关系在设计上应遵循里氏替换原则:子类必须完全兼容父类行为,父类出现处可替换为子类。

💡 组合优先示例

class Engine {};   // 引擎类
class Car {
private:Engine engine; // 组合而非继承(Car has an Engine)
};// 而非:
class Car : public Engine {};  // 错误继承

五、面试常见问题及回答 🚀

1. 问:何时使用继承?何时用组合?✅

  • 继承
    1. 当需要表达严格的"is-a"关系时(如Circle is a Shape
    2. 需要实现运行多态时
    3. 符合里氏替换原则的场景

  • 组合:当需要"has-a"关系或避免耦合时(如Car包含Engine

2. 问:为什么父类需要虚析构函数(virtual)?✅

  • 避免内存泄漏
    Base* p = new Derived();// 若基类析构非虚,仅调用Base::~Base() → 内存泄漏
    delete p; // 若~Base()非虚,仅调用~Base()导致Derived部分泄漏
    

3. 问:多重继承会导致什么问题,如何解决?✅

    1. 菱形继承问题(需虚继承解决)
      class A {};
      class B : virtual public A {};
      class C : virtual public A {};
      class D : public B, public C {};
      
    1. 增加复杂度,易引发命名冲突
    1. 推荐用接口继承+组合替代

4. 问:如何设计图形系统且支持多态绘制?✅

  • 具体实现代码示例
    class Shape {
    public:virtual double area() const = 0;virtual void draw() const = 0;virtual ~Shape() = default;
    };class Circle : public Shape {double radius;
    public:double area() const override { return 3.14 * radius * radius; }void draw() const override {cout << "○" << endl;}
    };
    

设计图形系统


总结 🛠️

  • 继承的优缺点
    优点是可以实现代码重用和多态;
    缺点是可能增加类之间的耦合(降低通用性),过度使用继承可能导致层次过深、结构复杂。
  • 组合优先于继承
    在可能的情况下,优先使用组合而不是继承,因为组合的耦合度较低。

通过合理使用泛化关系,可构建高扩展性的面向对象系统,但需警惕过度继承导致的维护复杂性。

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【微服务的数据一致性分发问题】究极解决方案

文章目录一、微服务数据分发1、简介2、典型场景&#xff08;1&#xff09;跨服务业务流程协同&#xff08;2&#xff09;数据副本同步&#xff08;读写分离&#xff09;&#xff08;3&#xff09;实时状态通知&#xff08;4&#xff09;数据聚合与统计分析&#xff08;5&#x…

挖币与区块链技术有怎样的联系?

挖币&#xff08;通常指加密货币挖矿&#xff09;与区块链技术有着紧密的联系&#xff0c;挖矿是区块链网络维持运行和安全的重要机制之一&#xff0c;具体联系如下&#xff1a;1. 挖矿是区块链共识机制的核心环节区块链通过“共识机制”确保全网节点对交易记录达成一致&#x…

C数据结构:二叉树(下)

C数据结构&#xff1a;二叉树&#xff08;下&#xff09; 1.二叉树递归结构遍历 2.例题 3.二叉树的性质 1.二叉树递归结构遍历 我们先创建一个如下图所示的二叉树。typedef int BTDataType; typedef struct BinaryTreeNode {BTDataType data;struct BinaryTreeNode* left;struc…

Linux系统的网络管理(一)

一、网络参数配置&#xff1a;搭建稳定网络基础网络参数配置是 Linux 网络管理的起点&#xff0c;根据操作方式可分为图形化配置、命令行配置和配置文件配置&#xff0c;不同方式适用于不同场景&#xff08;临时调试 / 永久生效&#xff09;。1. 图形化配置&#xff1a;依赖 Ne…

Web程序设计

一、控件基础 文本框、按钮事件的使用 <% Page Language"C#" AutoEventWireup"true" CodeFile"User_Login.aspx.cs" Inherits"User_Login" %><!DOCTYPE html><html xmlns"http://www.w3.org/1999/xhtml"&g…

复合设计模式

复合设计模式复合设计模式是一种结构模式&#xff0c;可让您统一处理单个对象和对象的组合。它允许您构建树状结构&#xff08;例如&#xff0c;文件系统、UI 层次结构、组织结构&#xff09;&#xff0c;客户端可以使用同一界面处理单个元素和元素组。它在以下情况下特别有用&…

使用 Prometheus 监控服务器节点:Node Exporter 详解与配置

前言 在上一篇文章中&#xff0c;我们介绍了如何在 CentOS 上部署 Prometheus 并使用 systemd 进行管理。本文将继续深入&#xff0c;讲解如何使用 Prometheus 监控服务器节点&#xff0c;重点介绍 Node Exporter 的作用、安装和配置方法。 Node Exporter 是 Prometheus 生态…

C# 编写一个XmlToDota的转换工具

以下代码可以将Labelme标注的旋转框Xml格式文件转换为Yolo标注格式的txt文件&#xff0c;以便用Yolo OBB训练自己的数据集&#xff1a;using System; using System.Collections.Generic; using System.IO; using System.Xml; using System.Linq; using System.Globalization;na…

[Android] 人体细胞模拟器1.5

[Android] 人体细胞模拟器1.5 链接&#xff1a;https://pan.xunlei.com/s/VOYVUieTpjNVJq-bMys4EEDGA1?pwdm7m6# 省流:这个软件的开发者有点逆天&#xff0c;一个模拟人体器官的软件&#xff0c;细致到有血液报告&#xff0c;还缝合了生理学和病理学&#xff0c;甚至还能做切…

【Linux基础知识系列】第一百一十篇 - 使用Nmap进行网络安全扫描

在网络安全管理中&#xff0c;了解网络中的设备、开放的端口以及运行的服务是至关重要的。Nmap&#xff08;Network Mapper&#xff09;是一个功能强大的开源工具&#xff0c;用于网络发现和安全审计。它可以扫描网络中的设备&#xff0c;识别开放的端口和运行的服务&#xff0…

【Linux仓库】进程的“夺舍”与“飞升”:exec 驱动的应用现代化部署流水线

&#x1f31f; 各位看官好&#xff0c;我是egoist2023&#xff01; &#x1f30d; Linux Linux is not Unix &#xff01; &#x1f680; 今天来学习exec系列的进程程序替换,从"fork"的"克隆"到"exec"的"重生"。 &#x1f44d; 如果觉…

Reachability Query

题目分析 该代码实现了一个动态集合管理系统&#xff0c;支持三种操作&#xff1a;合并集合、切换元素状态、查询集合中是否- 存在活跃元素。核心数据结构为并查集&#xff0c;结合状态标记数组和计数器。关键数据结构与函数 初始化 fa[N]&#xff1a;并查集父节点数组&#xf…

SSL移动接入方案和移动资源发布

一、SSL VPN概述SSL VPN是一种基于SSL/TLS协议的远程安全接入技术&#xff0c;因其广泛兼容Web浏览器&#xff0c;支持“无客户端”部署&#xff0c;具备易于使用和维护的特点。它通过插件系统支持非Web类TCP/UDP应用&#xff0c;并且支持对用户的访问可以做出限制&#xff0c;…

C++STL---count() 统计容器中特定元素出现次数

在 C 标准库中&#xff0c;count 是一个用于统计容器中特定元素出现次数的函数&#xff0c;定义在 <algorithm> 头文件中。它可以快速计算某个值在容器&#xff08;如数组、vector、list 等&#xff09;中出现的次数&#xff0c;避免手动编写循环计数的麻烦。 一、函数原…

Tesla自动驾驶域控制器(AutoPilot HW)的系统化梳理

目前网络上对Tesla自动驾驶硬件&#xff08;AP1-AP4、HW1.0-HW4.0&#xff09;迭代的相关介绍比较混乱&#xff0c;本文这里进行系统化梳理并澄清&#xff0c;并对一些错误进行更正。1、AutoPilot HW迭代图图1 AutoPilot HWMCU迭代图图2 AutoPilot HW 散热设计迭代图&#xff0…

C 语言:第 20 天笔记:typedef(类型重命名规则、应用场景与实战案例)

C语言&#xff1a;第20天笔记 内容提要 构造类型枚举类型typedef综合案例:斗地主预处理 构造类型&#xff1a;枚举类型 使用建议 如果定义不相干的常量&#xff0c;使用宏定义&#xff08;符号常量&#xff09;&#xff1b;如果需要定义一组相关联的常量&#xff08;如月份011、…

在 vue3 和 vue2 中,v-for 和 v-if 可以一起用吗,区别是什么

在 Vue 2 和 Vue 3 中&#xff0c;v-for 和 v-if 可以一起使用&#xff0c;但两者在处理顺序和推荐用法上存在明显区别&#xff0c;主要体现在优先级和最佳实践上&#xff1a; 1. Vue 2 中的 v-for 与 v-if优先级&#xff1a;v-for 的优先级高于 v-if。 这意味着 Vue 会先循环渲…

Linux-进程相关函数

文章目录Linux-进程相关函数父子进程关系父子进程地址空间getpid函数 获取本进程号getppid函数 获取当前进程的进程的父进程号getpgid函数 获取进程组号示例fork函数 创建进程区分父子进程exit函数 进程退出wait函数 等待子进程退出waitpid函数Linux-进程相关函数 每个进程都由…

数据挖掘 6.1 其他降维方法(不是很重要)

6.1 Other dimensionality reduction methods 6.1 其他降维方法 其他降维方法前言问题答案流形3 降维大纲3.1 线性方法3.2 非线性方法3.2.1 流形学习方法&#xff08;Manifold Learning&#xff09;3.2.2 概率方法&#xff08;Probabilistic Approaches&#xff09;3.2.3 拓扑数…

Unity中的特殊文件夹

一.工程路径获取print(Application.dataPath);只用于游戏开发编辑器模式下&#xff0c;游戏发布后此路径就不存在了二.Resources 资源文件夹//路径获取: //一般不获取 //只能使用Resources相关API进行加载 //如果硬要获取 可以用工程路径拼接print(Application.dataPath "…