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;
}