【面试攻略】模板和动态参数

#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

(0)
上一篇 2022年3月23日
下一篇 2022年3月23日

相关推荐