C/C++ 相关低耦合代码的设计

news2024/11/17 7:44:49

在我们设计C/C++ 程序的时候,有时需要两个类或者两个模块相互“认识”,或者两个模块间函数互相调用,假设我们正在开发一个网上商店,代表的网店客户的类必须要知道相关的账户。

UML图如下,这被称为环依赖,这两个类直接或间接地相互依赖。

一般我们都会采用结构体或类前置声明的方式,在解决此问题。

customer.h

#ifndef CUSTOMER_H_
#define CUSTOMER_H_

class Account;
class Customer
{
   // ...
   void setAccount(Account* account);
   {
       customerAccount = account;
   }
  //...
private:
   Account* customerAccount;
};
#endif

account.h

#ifndef ACCOUNT_H_
#define ACCOUNT_H_
class Account
{
 public:
      //...
     void setOwer(Customer* customer)
     {
           ower = customer;
     }
   //...
  private:
         Customer* ower;
}
#endif

老实说上面的方式确实可以消除编译器的错误,但是这种解决方案不够好。

下面的调用示例,存在一个问题,当删除Account的实例,Customer的实例仍然存在,且内部的指向Account的指针为空。使用或解引用此指正会导致严重的问题。

#include "account.h"
#include "customer.h"

//...
Account *account = new Accout{};
Customer *customer = new Customer{};
account->setOwer(customer);
customer->setAccount(account);

那有没有更好的做法呢,依赖倒置原则可以很好的解决此类问题。

依赖倒置原则

第一步是我们不在两个类中的其中一个访问另一个,相反,我们只通过接口进行访问。我们从Customer中提取Ower的接口,作为示例,Ower接口中声明一个纯虚函数,该函数必须由此接口类覆盖。

ower.h

#ifndef OWNER_H_
#define OWNER_H_

#include <memory>
#include <string>

class owner
{
   public:
       virtual ~owner()=default;
       virtual std::string getName() const = 0;
};
using OwnerPtr = std::shared_ptr<Owner>;
#endif

Customer.h

#ifndef CUSTOMER_H_
#define CUSTOMER_H_

#include "Owner.h"
#include "Account.h"

class Customer:public Owner
{
  public:
     void setAccount(AccountPtr account)
     {
            customerAccount =   account;    
     }
  virtual std::string getName() const override{
    //return string
  }

  private:
     Account customerAccount;
};
using CustomerPtr = std::shared_ptr<Customer>;
#endif

account.h

#ifndef ACCOUNT_H_
#define ACCOUNT_H_

#include "Owner.h"
class Account
{
   public:
       void setOwner(OwnerPtr owner)
       {
          this->owner = owner;
       }
   private:
      OwnerPtr owner;
};
using AccountPtr = std::shared_ptr<Account>;

现在设计完发现这两个模块间消除了环依赖。

C/C++ 通过回调函数和信号槽的方式降低模块的耦合行

为了降低模块功能代码的耦合性,我们经常采用回调函数或者信号槽的方式来联系两个模块。

回调函数的方式:

a.h

#pragma once
#ifndef A_H_
#define A_H_
#include <stdio.h>


int test(int c);

#endif

a.c

#include "a.h"
int test(int c)
{
    c = 0x11112;
    return c;
}

b.h

#pragma once
#ifndef B_H_
#define B_H_
#include <stdio.h>

typedef int (*PtrFunA)(int);

int testb(PtrFunA, int c);
#endif

b.c

#include "b.h"

int testb(PtrFunA a, int c)
{
    int ret = a(c);
    printf("%d\n", ret);
    return ret;
}

main.c

#include <stdio.h>
#include "a.h"
#include "b.h"
int main()
{
    testb(test,123);
}

这样做的好处降低代码的耦合性,是A模块的功能代码只写在A.C中。B.C的功能代码只写在B.C中,改进的后的回调函数可以用void*进行传参,在a.c中对void*进行判断,这是很多代码常做的操作。

信号槽的话则更加灵活性和代码的耦合度再次降低,后期在说,先写在这了。

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

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

相关文章

【GIS前沿】什么是新型基础测绘、内容、产品体系、特征?

《测绘法》指出&#xff0c;基础测绘是建立和维护全国统一的测绘基准和测绘系统&#xff0c;进行航天航空影像获取&#xff0c;建立和更新维护基础地理信息数据库&#xff0c;提供测绘地理信息应用服务等。 文章目录一、什么是新型基础测绘&#xff1f;二、新型基础测绘的特征三…

6、场景法

为什么使用场景法 现在的系统基本上都是由事件来触发控制流程的。如&#xff1a;我们申请一个项目&#xff0c;需先提交审批单据&#xff0c;再由部门经理审批&#xff0c;审核通过后由总经理来最终审批&#xff0c;如果部门经理审核不通过&#xff0c;就直接退回。每个事件触…

1.Docker Desktop安装设置

1.下载最新版本Download Docker Desktop | Docker 2.进行安装 2.1进行4.x版本安装 2.2最新版本出现问题 出现 docker desktop stopped 过一会后 quit退出&#xff0c;下载3.x版本 2.3继续安装 Enable Hyper-V windows Features 启动Hyper-V windows 虚拟化功能 百度百科-验证…

【GD32F427开发板试用】一、环境搭建与freertos移植

本篇文章来自极术社区与兆易创新组织的GD32F427开发板评测活动&#xff0c;更多开发板试用活动请关注极术社区网站。作者&#xff1a;chenjie 【GD32F427开发板试用】一、环境搭建与freertos移植 【GD32F427开发板试用】二、USB库移植与双USB CDC-ACM功能开发 【GD32F427开发板…

java集合类(属于工具类)概述

Java集合类可用于存储数量不等的对象&#xff0c;并可以实现常用的数据结构&#xff0c;如栈、队列等。除此之外&#xff0c;Java集合还可用于保存具有映射关系的关联数组。 Java集合大致可分为Set、List、Queue和Map四种体系&#xff1a; 其中Set代表无序、不可重复的集合&…

限制系统性能瓶颈的因素、衡量系统性能的指标

文章目录限制系统性能瓶颈的因素cpu内存磁盘IO网络IO异常数据库锁竞争衡量系统性能的指标响应时间吞吐量计算机资源分配使用率负载承受能力有时候我们的程序性能不高,需要提升性能,这个时候可以从以下几个角度去考虑是什么限制了我们的性能瓶颈.限制系统性能瓶颈的因素 cpu 有…

spring-bean的生命周期-【源码解析】-上

一、spring的bean概念Spring最重要的功能就是帮助程序员创建对象&#xff08;也就是IOC&#xff09;&#xff0c;而启动Spring就是为创建Bean对象做准备&#xff0c;所以我们先明白Spring到底是怎么去创建Bean的&#xff0c;也就是先弄明白Bean的生命周期。Bean的生命周期就是指…

RocketMq-dashboard:topic 5min trend 原理和源码分析(一)

本文阅读基础&#xff1a;使用或了解过rocketMq&#xff1b;想了解"topic 5min trend"背后的原理&#xff1b;想了解监控模式如何实现。RocketMq的dashboard&#xff0c;有运维页面&#xff0c;驾驶舱&#xff0c;集群页面&#xff0c;主题页面&#xff0c;消费者页面…

[羊城杯 2020]easyre 1题解

一步一个脚印地耐心攀登&#xff0c;就是别去看顶峰&#xff0c;而要专注于在爬的路。 ——黑泽明 目录 1.查壳 2.IDA静态分析main函数 3.研究三重加密 第一重加密 第二重加密 第三重加密 4.解密 1.查壳 64bit exe文件 2.IDA静态分析main函数 拖入IDA&#xff0c;找到…

芯片验证系列——Checker

在产生了有效的激励后&#xff0c;需要判断出不符合功能描述的行为。Checker就是用于查看DUT是否按照功能描述做出期望的行为&#xff0c;识别出所有的设计缺陷。 按照激励的生成方式和检查的功能点分布可以将验证划分为三种方式&#xff1a; 黑盒验证&#xff1a;验证环境不…

【Vue】前端工程化与 webpack

一、前端工程化前端开发1.1 小白眼中的前端开发会写 HTML CSS JavaScript 就会前端开发需要美化页面样式&#xff0c;就拽一个 bootstrap 过来需要操作 DOM 或发起 Ajax 请求&#xff0c;再拽一个 jQuery 过来需要快速实现网页布局效果&#xff0c;就拽一个 Layui 过来1.2 实…

redis事务详解

事务是逻辑上对数据的一组操作&#xff0c;这操作要么一次全部成功或者这操作全部失败&#xff0c;是不可分割的单位 四大特性 原子性&#xff0c;一致性&#xff0c;隔离性&#xff0c;持久性(ACID) redis的事务 redis是弱事务型数据库&#xff0c;并不具备ACID的全部特性 re…

python情感分析:基于jieba的分词及snownlp的情感分析!

情感分析&#xff08;sentiment analysis&#xff09;是2018年公布的计算机科学技术名词。 它可以根据文本内容判断出所代表的含义是积极的还是负面的&#xff0c;也可以用来分析文本中的意思是褒义还是贬义。 一般应用场景就是能用来做电商的大量评论数据的分析&#xff0c;…

【Linux】基础IO文件操作

目录 基础IO 重谈文件 重谈C语言的文件操作 系统文件IO 理解文件 文件描述符fd 0 & 1 & 2 文件描述符的分配规则 重定向 使用 dup2 系统调用 在minishell中添加重定向功能 缓冲区 理解缓冲区 再次理解缓冲区 基础IO 重谈文件 1、空文件&#xff0c;也要…

C++STL入门:string的基本使用小笔记

目录 一.string类简介 二.string类的常用成员接口 1.string类对象的构造函数接口 2. string类对象的容量操作接口 std::string::size std::string::length std::string::empty std::string::clear std::string::resize std::string::reserve 3.string类对象的访问及遍历操作…

【精品】k8s的CKA考题17道解析

目标一:记住命令关键单词 第4道题:scale replicas 第5道题:cordon、uncordon、drain 第8道题:target-port 目标二:完成操作要求 NoSchedule 查看工作节点的健康状态 ,确定集群中有多少节点为 Ready 状态,并且去除包含 NoSchedule 污点的节点。之后将数字写到/opt/repl…

Mybatis-Plus使用指南

1、了解Mybatis-Plus 1.1、Mybatis-Plus介绍 MyBatis-Plus&#xff08;简称 MP&#xff09;是一个 MyBatis 的增强工具&#xff0c;在 MyBatis 的基础上只做增强不做改变&#xff0c;为简化开发、提高效率而生。 官网&#xff1a;https://mybatis.plus/ 或 https://mp.baomi…

基础IO详解

目录 一、系统文件IO 1.1 open 1.1.1 open的第一个参数 1.1.2 open的第二个参数 1.1.3 open的第三个参数 1.1.4 open的返回值 1.2 close 1.3 write 1.4 read 二、文件描述符 2.1 进程与文件描述符 2.2 文件描述符的分配规则 三、重定向 3.1 自实现重定向原理 3.…

关于电流互感器电流以及采集电路理解

今天看了下零序电流互感器的作用&#xff0c;跟电路互感器的相似&#xff0c;这个相似是对于二次侧的电路检测功能相似&#xff1b;下面来记录下零序电流互感器以及二次侧采样电路&#xff08;1&#xff09;零序电流互感器&#xff0c;主要用于漏电检测从图中我们看到从断路器到…

L1、L2正则化的原理及适用场景

1. L1正则化&#xff0c;也称Lasso回归 1.1 含义 权值向量 中各元素的绝对值之和&#xff0c;一般记作 。 1.2 公式表示 添加了L1正则化的损失函数一般可表示为&#xff1a; 1.3 作用 L1正则常被用来解决过拟合问题&#xff1b; L1正则化容易产生稀疏权值矩阵&#x…