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

C++ 模板宏相关

C++ 模板宏相关

  • 一、模板的声明和定义(.hpp)
  • 二、定义一个简单的宏模板
  • 三、模板实现单例
  • 四、模板宏的实战案例


一、模板的声明和定义(.hpp)

可以看到我们把模板定义到.h中实现在.cpp中编译时会报错,应该把实现也放到一起可以用.hpp文件来组织
在这里插入图片描述

二、定义一个简单的宏模板

  • \ 表示宏没有结束
  • 2个# 表示拼接名称
  • VA_ARGS 获取变长参数(只能出现在宏定义的可变参数模板中)
#define TEST_TEMPLETE_CLASS(ClassName,Code,Str,...) \
template<class T> \
class F##ClassName \
{ \
public: \void Work() \{\printf(Str,__VA_ARGS__);\Code;\}\
private: \T* Value; \
};

如下是简单的使用方式

TEST_TEMPLETE_CLASS(TestClass, { std::cout << "Test Func" << std::endl; },"Str: %s \r\n","Hello")int main()
{FTestClass<int> TestClass;TestClass.Work();system("pause");return 0;
}

三、模板实现单例

在开发中有大量的单例需要定义,我们使用模板可以避免这种频繁的定义。
比如我们需要资源管理器、音频管理器

class AssetManager
{
public:void LoadAsset(){printf("LoadAsset Success \r\n");}
};class AudioManager
{
public:void PlayAudio(){printf("PlayAudio Success \r\n");}
};

我们只需要定义好类型,而单例交给模板去做

template<typename T>
class InstanceTemplete
{
public:static T* GetInstance();static void Dispose();private:static T* Instance;
};template<typename T>
T* InstanceTemplete<T>::Instance = nullptr;template<typename T>
T* InstanceTemplete<T>::GetInstance()
{if (Instance == nullptr){Instance = new T();}return Instance;
}template<typename T>
void InstanceTemplete<T>::Dispose()
{delete Instance;Instance = nullptr;
}

为了我们之后使用方便简洁,我们用宏包装一下

#define D_Instance_Manager(ManagerTypeClass)typedef InstanceTemplete<ManagerTypeClass> G##ManagerTypeClass;

以下是使用:

D_Instance_Manager(AssetManager)
D_Instance_Manager(AudioManager)int main()
{AssetManager* assetMgr = GAssetManager::GetInstance();assetMgr->LoadAsset();AudioManager* audioMgr = GAudioManager::GetInstance();audioMgr->PlayAudio();system("pause");return 0;
}

四、模板宏的实战案例

发送消息和接收消息通常需要解析消息,我们使用这个例子。


  • 在C++中,typedef用于为现有类型定义别名。这里,typedef unsigned char uint8;定义了一个名为uint8的别名,它等同于unsigned char。

  • 接下来,我们有一个模板类Message,它使用一个非类型模板参数ProtoNum,该参数的类型是uint8(即unsigned char)。非类型模板参数意味着我们用一个值而不是一个类型来实例化模板。

typedef unsigned char uint8;template<uint8 ProtoNum>
class Message
{};

下面是宏定义模板,目的就是定义出来不同的协议号对应的解析Message

#define DEFINE_NET_MESSAGE(Name,ProtoIndex,...) \
enum{ProtoNum_##Name = ProtoIndex}; \
template<> \
class Message<ProtoIndex> \
{ \
public: \template<typename ...ParamTypes> \static void Send(ParamTypes& ...Param) \{ \MessageHelper::SendMessage(Param...); \} \\\template<typename ...ParamTypes> \static void Receive(ParamTypes& ...Param) \{ \MessageHelper::ReceiveMessage(Param...); \} \
};class MessageHelper
{
public:template<typename ...ParamTypes>static void SendMessage(ParamTypes& ...Param){//发送printf("发送\r\n");}template<typename ...ParamTypes>static void ReceiveMessage(ParamTypes& ...Param){//接收printf("接收\r\n");}
};

以下是使用这个宏模板

DEFINE_NET_MESSAGE(Register, 0, char,int,float)
DEFINE_NET_MESSAGE(Login, 1, char,char)int main()
{Message<ProtoNum_Login>::Send();Message<ProtoNum_Register>::Send();char a = 'a';char b = 'b';int c = 111;float d = 2.3f;Message<ProtoNum_Login>::Receive(a,b);Message<ProtoNum_Register>::Receive(a, c, d);system("pause");return 0;
}
http://www.xdnf.cn/news/14846.html

相关文章:

  • 力扣网编程45题:跳跃游戏II之正向查找方法(中等)
  • 容声W60以光水离子科技实现食材“主动养鲜”
  • 爬虫-协议基础
  • XHTML 简介
  • 使用LIMIT + OFFSET 分页时,数据重复的风险
  • Spring Bean 控制销毁顺序的方法总结
  • stm32的三种开发方式
  • js游戏简单修改
  • 【每天一个知识点】子空间聚类(Subspace Clustering)
  • SpringCloud系列(50)--SpringCloud Stream消息驱动之实现消费者
  • Python Async/Await 异步编程详解
  • <script setup>中的setup作用以及和不带的区别对比
  • 【UnityAssetBundle】异步加载
  • 【ESP32-IDF笔记】09-UART配置和使用
  • 基于大模型的领域知识图谱构建--python语言实现
  • Qt处理USB摄像头开发说明与QtMultimedia与V4L2融合应用
  • 二叉树题解——二叉搜索树中第 K 小的元素【LeetCode】使用外部变量ans记录答案
  • MyChrome.exe与Selenium联动避坑指南:User Data目录冲突解决方案
  • 60天python训练营打卡day52
  • Python gmssl.SM4使用案例
  • 动手学深度学习-学习笔记(总)
  • IDEA中application.yml配置文件不自动提示解决办法
  • 运算方法和运算器补充
  • 【AI大模型面试八股文】大模型训练中如何应对灾难性遗忘问题?
  • Swagger 安装使用教程
  • RabbitMQ 4.1.1初体验
  • 一个简单的分布式追踪系统
  • 区块链技术在物联网(IoT)中的核心应用场景
  • 利用TCP协议,创建一个多人聊天室
  • 图灵完备之路(数电学习三分钟)----数据选择器与总线