C++使用策略模式,减少使用switch...case...

news2024/11/27 20:49:32

目录

  • 原理
  • 函数
  • 类+模板函数
    • 使用switch...case...
    • 不使用switch...case...
  • 知识点
    • decltype
    • std::remove_reference

原理

在这里插入图片描述

函数

#include <iostream>
#include <functional>
#include <map>

void fun1(int a, int b)
{
	std::cout << "fun1 : a ="<<a<<"	b ="<<b;
}


void fun2(int a, int b)
{
	std::cout << "fun2 : a =" << a << "	b =" << b;
}

int main()
{

	// 可以改变这个值来调用不同的函数
	int id = 1;

#if 0
	switch (id)
	{
	case 1:
		fun1(0, 0);
		break;
	case 2:
		fun1(0, 0);
		break;
	}
#endif
	
	std::map<int, std::function<void(int,int)>> functionMap;

	functionMap[1] = [](int a, int b) { fun1(a,b); };
	functionMap[2] = [](int a, int b) { fun2(a, b); };

	
	if (functionMap.find(id) != functionMap.end()) {
		// 调用对应的函数并传递参数
		functionMap[id](0,0);
	}
	else {
		std::cout << "Invalid id" << std::endl;
	}

	return 0;
}

类+模板函数

因为工作职位低,无权对父类进行修改;
业务上又大量使用switch…case…操作模板函数;搞得代码量暴涨!

使用switch…case…

#include <iostream>
#include <functional>
#include <map>
#include <string>
#include <tuple>
#include <type_traits>

// 因为没有Equip的修改权限
struct Equip {
	std::string code;       //装备
};

struct FATable:public Equip {
	int idFA;               //方案ID
	std::string nameId;     //名称ID
	std::string equipId;    //装备ID
	int equipNum;           //装备数量
public:
	void write(int info) {
		std::cout << "FATable = " << info;
	};
};

struct NTable {
	std::string name;       //装备名称
	std::string nameId;     //装备ID
	int classify;           //分类ID
public:
	void write(int info) {
		std::cout << "NTable = " << info;
	};
};

struct CTable {
	int classify;           //分类ID
	std::string className;  //分类名称
public:
	void write(int info) {
		std::cout << "CTable  = "<< info;
	};
};

template<typename T>
inline void writeIn(int info) {
	T().write(info);
};

int main()
{

	// 可以改变这个值来调用不同的函数
	const int id = 1;

#if 1
	switch (id)
	{
	case 0:
		writeIn<FATable>(0);
		break;
	case 1:
		writeIn<NTable>(0);
		break;
	case 2:
		writeIn<CTable>(0);
		break;
	}
#endif
	
	return 0;
}

不使用switch…case…

#include <iostream>
#include <functional>
#include <map>
#include <string>
#include <tuple>
#include <type_traits>

// 因为没有Equip的修改权限
struct Equip {
	std::string code;       //装备
};

struct FATable:public Equip {
	int idFA;               //方案ID
	std::string nameId;     //名称ID
	std::string equipId;    //装备ID
	int equipNum;           //装备数量
public:
	void write(int info) {
		std::cout << "FATable = " << info;
	};
};

struct NTable {
	std::string name;       //装备名称
	std::string nameId;     //装备ID
	int classify;           //分类ID
public:
	void write(int info) {
		std::cout << "NTable = " << info;
	};
};

struct CTable {
	int classify;           //分类ID
	std::string className;  //分类名称
public:
	void write(int info) {
		std::cout << "CTable  = "<< info;
	};
};

template<typename T>
inline void writeIn(int info) {
	T().write(info);
};

int main()
{

	// 可以改变这个值来调用不同的函数
	const int id = 1;

	std::tuple<FATable, NTable, CTable> g_type = { FATable(), NTable(), CTable()};

	// 使用 decltype 来获取 g_type 中的元素类型,并将其命名为 _mT。
	using  _mT = decltype(std::get<id>(g_type));

	// 使用 std::remove_reference 来移除 _mT 类型的引用修饰符,将结果命名为 CleanType。
	using CleanType = typename std::remove_reference<_mT>::type;

	// 将 CleanType 作为模板参数传递
	writeIn<CleanType>(0);
	return 0;
}

知识点

decltype

decltype 是 C++11 引入的一个关键字,用于获取表达式的类型。它可以用于编译时推导表达式的类型,而不需要显式地指定类型。

  • 以下是 decltype 的一些重要知识点:

decltype 的语法:decltype(expression)

  • expression 是一个表达式,可以是变量、函数调用、成员访问等。

  • decltype 的返回类型:

如果 expression 是一个标识符或类成员访问表达式,decltype 返回该标识符或成员的类型。

如果 expression是一个函数调用表达式,decltype 返回函数的返回类型。

如果 expression是一个右值表达式,decltype返回右值的类型。

如果 expression 是一个左值表达式,decltype 返回左值的引用类型。

  • decltype 的应用场景:

在模板编程中,可以使用 decltype 推导模板参数的类型,以便在编译时确定类型。

可以使用 decltype 推导 lambda表达式的返回类型。

可以使用 decltype 推导复杂表达式的类型,避免手动指定类型。

-以下是一些使用 decltype 的示例:

	int x = 42;
	decltype(x) y;					// y 的类型为 int

	std::vector<int> vec = { 1, 2, 3 };
	decltype(vec.size()) size;		// size 的类型为 std::vector<int>::size_type

	auto lambda = [](int a, int b) -> int { 
		std::cout << "a + b  = " << a + b;
		return a + b; 
	};
	decltype(lambda) func = lambda;	// func 的类型为 lambda 表达式的类型
	func(1,1);

	template <typename T, typename U>
	auto add(T t, U u) -> decltype(t + u) {
		return t + u;
	}
	auto result = add(3, 4.5);		// result 的类型为 double

#include <iostream>
#include <typeinfo>
int main() {
     auto f = []()->void {
        std::cout << "hello---19" << std::endl;
     };
     using FunctionType = decltype(f);              // 使用 decltype(f) 定义类型别名 FunctionType
     std::cout << typeid(f).name() << std::endl;    // 输出类型名称
     std::cout << typeid(FunctionType).name() << std::endl;  // 输出类型别名的名称
     FunctionType func = f;                          // 使用类型别名创建变量,并将 f 赋值给它
     func();  // 调用函数对象
     /*
         使用 decltype 推导出的函数类型,不能直接声明一个未初始化的变量并调用它
         错误用法:
         FunctionType func;
         func();
     */
     return 0;
}

在这里插入图片描述
在这里插入图片描述

std::remove_reference

std::remove_reference 是 C++ 标准库中的一个模板元函数,用于移除类型的引用修饰符
当您使用std::remove_reference 时,它将返回一个新类型,该类型是从给定类型中移除了引用修饰符的版本。

  • 以下是 std::remove_reference 的示例用法:
#include <iostream>
#include <type_traits>

int main() {
    // 定义一个带有引用修饰符的类型
    using TypeWithReference = int&;

    // 使用 std::remove_reference 移除引用修饰符
    using TypeWithoutReference = 
    std::remove_reference<TypeWithReference>::type;

    // 输出移除引用修饰符后的类型名称
    std::cout << "Type without reference: " 
    << typeid(TypeWithoutReference).name() << std::endl;

    return 0;
}

在这个示例中,TypeWithReference 是一个带有引用修饰符的类型,然后我们使用 std::remove_reference 来移除引用修饰符,得到了 TypeWithoutReference。最后,我们输出了移除引用修饰符后的类型名称。

请注意,在 C ++14及更高版本中,你可以使用简化形式 std :: remove _ reference _ t 代替
typename std :: remove _ reference < T >:: type以缩短代码:

using CleanType = std::remove_reference_t<TypeWithReference>;

这提供了相同的结果,即从类型中去除引用

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

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

相关文章

学生成绩的增删改查

接上一篇MySQL数据库与其管理工具Navicat link 1.下载JDBC 可以登录MySQL的官方网站&#xff1a;www.mysql.com&#xff0c;下载JDBC-MySQL数据库驱动&#xff08;JDBC Driver for MySQL&#xff09;下载mysql-connector-java-5.1.40.zip后&#xff0c;将该zip文件解压至硬盘&a…

当使用RSA加密,从手机前端到服务器后端的请求数据存在+

将转成了空格&#xff0c;导致解密出错 将空格转成了

Numpy 实现基尼指数算法的决策树

基尼系数实现决策树 基尼指数 Gini ⁡ ( D ) 1 − ∑ k 1 K ( ∣ C k ∣ ∣ D ∣ ) 2 \operatorname{Gini}(D)1-\sum_{k1}^{K}\left(\frac{\left|C_{k}\right|}{|D|}\right)^{2} Gini(D)1−k1∑K​(∣D∣∣Ck​∣​)2 特征 A A A条件下集合 D D D的基尼指数&#xff1a; Gi…

『VUE3后台—硅谷甄选』

一、准备前期 pnpm create vite

学习Python的未来前景分析

文章目录 前言学python可以干什么如果具备Python编程&#xff0c;能用Python做什么&#xff1a;学Python语言能干什么1.常规软件开发2.科学计算3.自动化运维4.云计算 学python编程对未来的影响关于Python技术储备一、Python所有方向的学习路线二、Python基础学习视频三、精品Py…

2024年江苏省职业院校技能大赛信息安全管理与评估 第二阶段学生组(样卷)

2024年江苏省职业院校技能大赛信息安全管理与评估 第二阶段学生组&#xff08;样卷&#xff09; 竞赛项目赛题 本文件为信息安全管理与评估项目竞赛-第二阶段样题&#xff0c;内容包括&#xff1a;网络安全事件响应、数字取证调查、应用程序安全。 本次比赛时间为180分钟。 …

星钻图形输出

答案&#xff1a; #include <stdio.h> int a 0, b 0; void printLine(int a , int b) //输出一行包含&#xff1a;若干个空格 若干个*&#xff0c;第一&#xff0c;二个参数为空格数和*数&#xff1b; (定义一个星钻输出函数) {while (a--) //打印a个空格{printf(…

小程序左右侧边栏

效果 点击左侧边栏&#xff0c;右侧会定位到对应内容&#xff1b; 右侧滑动&#xff0c;左侧也会显示对应的高亮&#xff1b; 也就是左右联动的效果 项目场景 tocc-app 应急巡检 传入数据: 左侧点击&#xff0c;右侧滚动到对应位置 点击左侧导航条&#xff0c;就计算出右…

JavaScript面向对象编程的奥秘揭秘:掌握核心概念与设计模式

​&#x1f308;个人主页&#xff1a;前端青山 &#x1f525;系列专栏&#xff1a;JavaScript篇 &#x1f516;人终将被年少不可得之物困其一生 依旧青山,本期给大家带来JavaScript篇专栏内容:JavaScript-面向对象 目录 什么是面向对象&#xff1f; 类与对象的主要区别 创建…

【数据结构】- 详解哈夫曼树(用 C 语言实现哈夫曼树的构造和哈夫曼编码)

目录 一、哈夫曼树的基本概念 二、哈夫曼树的构造算法 2.1 - 哈夫曼树的构造过程 2.2 - 哈夫曼树的存储表示 2.3 - 算法实现 三、哈夫曼编码 3.1 - 哈夫曼编码的主要思想 3.2 - 哈夫曼编码的性质 3.3 - 算法实现 一、哈夫曼树的基本概念 哈夫曼树的定义&#xff0c;涉…

电脑字体大小怎么设置?学会这3个方法,轻松调节!

“感觉我近视又加深了&#xff0c;最近看电脑居然感觉字体有点小。我想把字体放大一点但却不知道应该怎么操作&#xff0c;有没有朋友可以指导一下我呀&#xff1f;” 在我们的日常生活中&#xff0c;电脑已经成为我们获取信息、交流和娱乐的重要工具。字体大小作为电脑显示的基…

厦门基础城建中排水管网作用,助力提升城市韧性

在厦门这个美丽的海滨城市&#xff0c;城市建设与发展日新月异&#xff0c;其中&#xff0c;城市生命线下的排水管网监测系统作为城市基础设施的重要组成部分&#xff0c;对保障城市安全、提升城市品质发挥着关键作用。 对于厦门城市建设中的排水管网监测系统安装策略 1. 合理…

【头歌系统数据库实验】实验2 MySQL软件操作及建库建表建数据

目录 第1关&#xff1a;创建数据库 第2关&#xff1a;创建供应商表S&#xff0c;并插入数据 第3关&#xff1a;创建零件表P&#xff0c;并插入数据 第4关&#xff1a;创建工程项目表J&#xff0c;并插入数据 第5关&#xff1a;创建供应情况表SPJ&#xff0c;并插入数据 …

软件开发文档的内容

软件开发文档是开发过程中用于记录、指导和沟通的重要工具。它可以包含多个文档&#xff0c;每个文档都有其特定的格式和目的。以下是一些常见的软件开发文档及其可能的格式&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#…

模拟目录管理 - 华为OD统一考试(C卷)

OD统一考试(C卷) 分值: 200分 题解: Java / Python / C++ 题目描述 实现一个模拟目录管理功能的软件,输入一个命令序列,输出最后一条命令运行结果。 支持命令: 1)创建目录命令: mkdir 目录名称,如mkdir abc为在当前目录创建abc目录,如果已存在同名目录则不执行任何操作…

HTML程序大全(2):通用注册模版

一、正常情况效果 二、某项没有填写的效果 三、没有勾选同意项的效果 四、代码 <!DOCTYPE html> <html> <head><meta charset"UTF-8"><title>注册</title><style>body {font-family: Arial, sans-serif;background-color…

小航助学题库白名单竞赛考级蓝桥杯等考scratch(16级)(含题库教师学生账号)

需要在线模拟训练的题库账号请点击 小航助学编程在线模拟试卷系统&#xff08;含题库答题软件账号&#xff09; 需要在线模拟训练的题库账号请点击 小航助学编程在线模拟试卷系统&#xff08;含题库答题软件账号&#xff09;

【重点】【矩阵】48. 旋转图像

题目 参考答案 法1&#xff1a;辅助矩阵 class Solution {public void rotate(int[][] matrix) {int n matrix.length;int[][] newMatrix new int[n][];for (int i 0;i < n; i) {newMatrix[i] matrix[i].clone();}for (int i 0; i < n; i) {for (int j 0; j <…

代码随想录算法训练营第四十四天 _ 动态规划_完全背包问题、518.零钱兑换II、377.组合总和IV。

学习目标&#xff1a; 动态规划五部曲&#xff1a; ① 确定dp[i]的含义 ② 求递推公式 ③ dp数组如何初始化 ④ 确定遍历顺序 ⑤ 打印递归数组 ---- 调试 引用自代码随想录&#xff01; 60天训练营打卡计划&#xff01; 学习内容&#xff1a; 完全背包问题 – 二维dp数组 动…

sklearn随机森林 测试 路面点云分类

一、特征5个坐标 坐标-特征-类别 训练数据 二、模型训练 记录分享给有需要的人&#xff0c;代码质量勿喷 import numpy as np import pandas as pd import joblib#region 1 读取数据 dir D:\\py\\RandomForest\\ filename1 trainRS filename2 .csv path dirfilename1file…