武侠世界2-try catch思考

以前一直不知道trycatch具体应用到什么地方,之前待过的几家公司也看不到有类似的代码。从网上搜来的,描述trycatch优点有下面几点。1、把错误处理和真正的工作分开来;  2、代码更易组织,更清晰,复杂的工作任务更容易实现;  3、毫无疑问,更安全了,不至于由于一些小的疏忽而使程序意外崩溃了;  4、由于C++中的trycatch可以分层嵌套,所以它…

大家好,又见面了,我是你们的朋友全栈君。

以前一直不知道try catch具体应用到什么地方,之前待过的几家公司也看不到有类似的代码。
从网上搜来的,描述try catch优点有下面几点。
1、 把错误处理和真正的工作分开来;
  2、 代码更易组织,更清晰,复杂的工作任务更容易实现;
  3、 毫无疑问,更安全了,不至于由于一些小的疏忽而使程序意外崩溃了;
  4、 由于C++中的try catch可以分层嵌套,所以它提供了一种方法使得程序的控制流可以安全的跳转到上层(或者上上层)的错误处理模块中去。(不同于return语句,异常处理的控制流是可以安

全地跨越一个或多个函数 )。
  5、 还有一个重要的原因就是,由于目前需要开发的软件产品总是变得越来越复杂、越来越庞大,如果系统中没有一个可靠的异常处理模型,那必定是一件十分糟糕的局面。

//总结出来就是:减少了判断语句的使用(if),程序更加简洁明了,程序更加健壮。
直到在武侠世界源码里面看到下面的一些代码:
在World的main函数里

__ENTER_FUNCTION
__LEAVE_FUNCTION
这两个宏的定义是
#define __ENTER_FUNCTION {try{

#define __LEAVE_FUNCTION }catch(…){AssertSpecial(FALSE,__FUNCTION__);}}
也就是说武侠世界里的大多数函数的开头和结尾都会用到这两个函数,至于在代码在哪里抛出错误呢?
下面是武侠世界World的主循环函数

void ServerManager::Loop( )
{
__ENTER_FUNCTION

	while( IsActive() )
	{
		BOOL ret = FALSE ;
		UINT uTime = g_pTimeManager->CurrentTime() ;

		_MY_TRY
		{
			ret = Select( ) ;
			Assert( ret ) ;

			ret = ProcessExceptions( ) ;
			Assert( ret ) ;

			ret = ProcessInputs( ) ;
			Assert( ret ) ;

			ret = ProcessOutputs( ) ;
			Assert( ret ) ;
		}
		_MY_CATCH
		{
		}

		_MY_TRY
		{
			ret = ProcessCommands( ) ;
			Assert( ret ) ;
		}
		_MY_CATCH
		{
		}

		_MY_TRY
		{
			ret = HeartBeat( ) ;
			Assert( ret ) ;
		}
		_MY_CATCH
		{
		}

		_MY_TRY
		{
			ret = g_pOnlineUser->HeartBeat( uTime ) ;
			Assert( ret ) ;
		}
		_MY_CATCH
		{
		}

        _MY_TRY
        {
            ret = g_pCountryManager->HeartBeat( uTime ) ;
            Assert( ret ) ;
        }
        _MY_CATCH
        {
        }

		_MY_TRY
		{
			ret = g_pTeamList->HeartBeat( uTime ) ;
			Assert( ret ) ;
		}
		_MY_CATCH
		{
		}

		_MY_TRY
		{
			ret = g_pChatCenter->HeartBeat( uTime ) ;
			Assert( ret ) ;
		}
		_MY_CATCH
		{
		}

		_MY_TRY
		{
			ret = g_pGuildManager->HeartBeat( uTime ) ;
			Assert( ret ) ;
		}
		_MY_CATCH
		{
		}

		_MY_TRY
		{
			ret = g_pCityManager->HeartBeat( uTime ) ;
			Assert( ret ) ;
		}
		_MY_CATCH
		{
		}

		_MY_TRY
		{
			ret = g_pMailCenter->HeartBeat( uTime ) ;
			Assert( ret ) ;
		}
		_MY_CATCH
		{
		}

		_MY_TRY
		{
			ret = g_pSceneInfo->HeartBeat( uTime ) ;
			Assert( ret ) ;
		}
		_MY_CATCH
		{
		}

		_MY_TRY
		{
			ret = g_pWorldTimeInfo->HeartBeat( uTime ) ;
			Assert( ret ) ;
		}
		_MY_CATCH
		{
		}
	};

__LEAVE_FUNCTION
}

其实这写得相当明了,Select( ) 就是接收网络信息,HeartBeat( )就是心跳等等。
里面的Assert是自己定义的一个宏

#define Assert(expr) ((VOID)((expr)?0:(__assert__(__FILE__,__LINE__,__FUNCTION__,#expr),0)))
#define AssertEx(expr,msg) ((VOID)((expr)?0:(__assertex__(__FILE__,__LINE__,__FUNCTION__,#expr,msg),0)))
#define AssertSpecial(expr,msg) ((VOID)((expr)?0:(__assertspecial__(__FILE__,__LINE__,__FUNCTION__,#expr,msg),0)))

VOID __assert__ ( const CHAR * file , UINT line , const CHAR * func , const CHAR * expr )
{
	CHAR szTemp[1024] = {0};
	
#ifdef __LINUX__ //换个格式
	sprintf( szTemp, "[%s][%d][%s][%s]\n", file, line, func, expr ) ;
#else
	sprintf( szTemp, "[%s][%d][%s][%s]", file, line, func, expr ) ;
#endif
	__show__(szTemp) ;
}

VOID __show__( const CHAR* szTemp )
{

#ifdef __LINUX__
	printf("Assert:%s",szTemp);
#endif

	//保存日志
#ifndef GAME_CLIENT
	FILE* f = fopen( "./Log/assert.log", "a" ) ;
	if (f != NULL)
	{
		fwrite( szTemp, 1, strlen(szTemp), f ) ;
		fwrite( "\r\n", 1, 2, f ) ;
		fclose(f) ;
	}
#endif

#if defined(__WINDOWS__)
	static MyLock lock ;
	if( g_Command_Assert!=1 )
	{
		lock.Lock() ;
		INT iRet = ::MessageBoxA( NULL, szTemp, "异常", MB_OK ) ;
		lock.Unlock() ;
	}
#elif defined(__LINUX__)
	
#endif

#ifdef GAME_CLIENT
	throw(std::string(szTemp));
#else
	throw(1);
#endif
}

最终会在__show__中throw错误,做成了一个统一的错误处理接口。
这是相当于用
Assert( ret ) ;

代替了
if ( !ret )
{

printf(“error\n”);
return;
}
这样使程序更清晰明了。
至于为什么还要定义
#define _MY_TRY try
#define _MY_CATCH catch(…)
大家可以思考一下

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/125686.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • hive sql语句和mysql用法区别存档

    hive sql语句和mysql用法区别存档写在前面以下功能版本:mysql版本:5.6.17hive版本:2.2.41、GROUP_CONCAT先看下面数据表test_group:(1)简单情况需求如下:写出一个sql语句,按照category分组,并把组内的name使用“;”分隔符连接。①mysql中SELECT category, GROUP_CONCAT(nameSEPARATOR";&quo

  • spring自定义注解实现(spring里面的注解)

    java注解:附在代码中的一些元信息,用于在编译、运行时起到说明、配置的功能。一、元注解java提供了4中元注解用于注解其他注解,所有的注解都是基于这四种注解来定义的。@Target注解:用于描述注解的使用范围,超出范围时编译失败。 取值类型(ElementType):  1.CONSTRUCTOR:用于描述构造器  2.FIELD:用于描述域(成

  • 手机钓鱼网站生成器_2021QQ空间钓鱼源码

    手机钓鱼网站生成器_2021QQ空间钓鱼源码欢迎访问我的网站http://ff999.cn里面有最新各种钓鱼程序源码提供下载QQ钓鱼YY钓鱼程序源码

  • 在Ubuntu下使用workon时出现workon: command not found错误「建议收藏」

    在Ubuntu下使用workon时出现workon: command not found错误「建议收藏」然后执行1.接着,我们需要配置下~/.bashrc,将virtualenv添加进去:    即将:    exportWORKON_HOME=$HOME/.virtualenvs    source/usr/local/bin/virtualenvwrapper.sh    复制到~/.bashrc中,保存退出2.让bashrc生效:执行source~/.bashrc命令…

  • perl文件句柄_perl文件句柄信号引用

    perl文件句柄_perl文件句柄信号引用perl哈希操作# 文件句柄,标准文件句柄有STDINSTDOUTSTDERRDATAARGVARGVOUT# 建立名字为TEXTFILE的文件句柄,<表示读文件openTEXTFILE,”<“,”a.txt”;while(<TEXTFILE>){print$_;}closeTEXTFILE;#openTEXTFILE1,”>”,”b.txt”;#>表示写文件,如果文件不存在,则会创建文件,输入文字覆盖原

    2022年10月18日
  • java面试题笔试题_外贸函电考试题和答案

    java面试题笔试题_外贸函电考试题和答案声明:有人说,有些面试题很变态,个人认为其实是因为我们基础不扎实或者没有深入。本篇文章来自一位很资深的前辈对于最近java面试题目所做的总结归纳,有170道题目,知识面很广,而且这位前辈对于每个题都自己测试给出了答案,如果你对某个题有疑问或者不明白,可以电脑端登录把题目复制下来然后发表评论,大家一起探讨,也可以电脑端登录后关注我给我发私信,我们一起进步!以下内容来自这位前辈2013年年底的…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号