【面试攻略】模板和动态参数
程序员文章站
2022-03-05 12:27:23
#pragma once#include "BaseGameType.h"#include #include "Log/Log.h"#include "Serialize/Stream.h"#include "GameDefine.h"#pragma pack(push,1)template struct StaticVector{public:StaticVector(){m_ve....
#pragma once
#include "BaseGameType.h"
#include <vector>
#include "Log/Log.h"
#include "Serialize/Stream.h"
#include "GameDefine.h"
#pragma pack(push,1)
template <typename T, TUint32 N>
struct StaticVector
{
public:
StaticVector()
{
m_vecLen = 0;
}
~StaticVector(){}
Tint32 GetSize() const //获取容器的总容量
{
return N;
}
Tint32 GetLen() const //获取数据的长度
{
return m_vecLen;
}
void Add(T &Data)
{
if(m_vecLen >= N)
{
Log::Instance()->WriteLog(enLogType_Error,"StaticVector::Add错误");
return ;
}
m_vecData[m_vecLen++] = Data;
}
T* GetDataHead() //获取首地址
{
return m_vecData;
}
T& GetData(TUint32 nIndex) //获取指定位置数据
{
if(nIndex < 0 || nIndex >= m_vecLen)
{
Log::Instance()->WriteLog(enLogType_Error,"StaticVector::GetData错误");
return (T&)m_vecData[0];
}
return (T&)m_vecData[nIndex];
}
void SetData(TUint32 nIndex, T& Data)
{
if(nIndex < 0 || nIndex >= m_vecLen)
{
Log::Instance()->WriteLog(enLogType_Error,"StaticVector::SetData错误");
return ;
}
m_vecData[nIndex] = Data;
}
T& operator [] (TUint32 nIndex) const
{
if(nIndex < 0 || nIndex >= m_vecLen)
{
Log::Instance()->WriteLog(enLogType_Error,"StaticVector::[]错误");
return (T&)m_vecData[0];
}
return (T&)m_vecData[nIndex];
}
void clear()
{
m_vecLen = 0;
}
void Serialize( Stream& stream )
{
TUint16 nLen = GetLen();
stream.Write(nLen);
for (int i=0; i < nLen; i++)
{
stream.Write(GetData(i));
}
}
bool DeSerialize( Stream& stream )
{
TUint16 nLen = 0;
if (!stream.Read(nLen))
return false;
for (TUint16 i=0; i < nLen; i++)
{
if(GetSize() - GetLen() <=0 )
return false;
T data;
if (!stream.Read(data))
return false;
Add(data);
}
return true;
}
protected:
T m_vecData[N];
TUint32 m_vecLen;
};
#pragma pack(pop)
至于为什么要用静态容器,是因为游戏开发玩家数据需要用到很多容器,而如果要用内存池,就必须提前知道玩家的最大内存消耗申请内存。
void Log::WriteCriticalError(const char *pszParam, ...)
{
if(pszParam == NULL)
return;
AutoLock locker(logLocker);
va_list va;
va_start(va, pszParam);
int nLen = 0;
char szResult[LOG_BUFFER_SIZE];
time_t t = time(0);
tm* Tm = localtime(&t);
nLen = strftime(szResult, LOG_BUFFER_SIZE, "%Y-%m-%d %H:%M:%S ", Tm);
#ifdef WIN32
nLen += vsnprintf_s(szResult + nLen, LOG_BUFFER_SIZE - nLen, _TRUNCATE, pszParam, va);
#else
nLen += vsprintf(szResult + nLen, pszParam, va );
#endif
nLen += sprintf(szResult + nLen, "\r\n");
printf(szResult);
#ifdef WIN32
MessageBoxA(NULL,szResult,"严重错误!",MB_OK);
#else
WriteLog(enLogType_Error,szResult);
#endif
}
void Log::PrintConsole(const char *pszParam, ...)
{
int length = strlen(pszParam);
if(pszParam == NULL || LOG_BUFFER_SIZE <= length)
return;
AutoLock locker(logLocker);
char szResult[LOG_BUFFER_SIZE];
int resultLen = 0;
va_list va;
va_start(va, pszParam);
resultLen = FormatWrite(enLogType_Msg,szResult,sizeof(szResult),pszParam, va);
va_end(va);
printf(szResult);
}
void Log::WriteLog(enLogType LogType, const char *pszParam, ...)
{
int length = strlen(pszParam);
if(pszParam == NULL || enLogType_Max <= LogType || LOG_BUFFER_SIZE <= length)
return;
if(CanWrite[LogType] == false)
return;
char szResult[LOG_BUFFER_SIZE];
int resultLen = 0;
va_list va;
va_start(va, pszParam);
resultLen = FormatWrite(LogType,szResult,sizeof(szResult),pszParam, va);
va_end(va);
LogSaveData data;
data.m_type = LogType;
data.bIsUTF8 = false;
data.m_count = resultLen;
data.m_data = szResult;
{
AutoLock locker(logLocker);
m_lstLogData.push_back(data);
}
m_WaitEvent.SetEvent();
}
比如,我们要封装一个自己的写log函数,就需要动态参数。
参考资料
C++ 模板 https://www.runoob.com/cplusplus/cpp-templates.html
C++学习之可变参数的函数与模板 https://songlee24.github.io/2014/07/22/cpp-changeable-parameter/
本文地址:https://blog.csdn.net/q277055799/article/details/109251240
下一篇: 单机和弱联网游戏内购,白嫖的机会来了
推荐阅读
-
C#_Excel数据读取与写入_自定义解析封装类_支持设置标题行位置&使用excel表达式收集数据&单元格映射&标题映射&模板文件的参数数据替换(第二版-增加深度读取和更新功能)
-
PHP面试:实现动态获取函数参数的方法
-
Android面试题: 动态代理和代理模式
-
荐 javascript从入门到跑路-----小文的js学习笔记(17)------动态属性、复制变量值、传递参数和检测类型
-
MySQL DDL--ghost执行模板和参数
-
【常见笔试面试算法题12续集二】动态规划算法案例2矩阵最小路径和练习题
-
Python动态参数/命名空间/函数嵌套/global和nonlocal
-
攻略前端面试官(二):作用域和闭包
-
Mybatis 不确定条件查询(动态语句where和if)借助实体类封装参数
-
攻略前端面试官(一):JS的数据类型和内存机制浅析