如何写出健壮的C++代码?

这个问题是没有完整的答案的,我们永远在路上。

还有一种说法是,要写出健壮的C++代码,你要先能写出健壮的代码。

扯远了,回到话题。

昨天写了个类,功能是从字符串中读取算术表达式,计算后返回结果。实际上就是Python的eval()函数,不过C++和AS3都没有这个功能,所以要自己写一个。实现也比较简单,首先是要解析字符串生成逆序波兰式,然后再递归运算逆序波兰式得到结果。每个波兰式节点有以下定义:

enum RPN_ENTRY_TYPE
{
    OPERATOR_TYPE = 0,
    OPERAND_TYPE,
}

struct RPN_ENTRY
{
    RPN_ENTRY_TYPE eType;
    union
    {
        char chOperator;
        int nOperand;
    }
}

每个节点有可能保存着操作符(operator)或者操作数(operand),有一个枚举用以标识当前节点是什么类型,随后跟着一个存放着操作符或操作数的联合体。

继续阅读

关于C++变长参数的一些细节

存在仅含变长参数的函数吗?
当然可以,至少编译器不会报错。你可以像这样定义一个仅含变长参数的函数:

void foo(...)
{
    //...
}

不过这样的函数基本上没什么用,主要原因是你无法取出它的参数。C++通过宏va_start以及va_arg从函数的变长参数列表中取值,其中va_start用以定位变长参数列表的起始地址,这需要借助于参数列表中最后一个固定参数:

var bar(int firstArg, ...)
{
    va_list pArgs;
    va_start(pArgs, firstArg);
    int nextArg = va_arg(pArgs, int);
}

当然,由于函数的参数都在栈中,因此也许有些十分诡异的手段可以直接从栈里将参数抠出来,不过这些用法太高端,我也不懂。
继续阅读

仅将SWF文件用作资源打包

使用Flash开发网页游戏少不了与各种美术资源打交道。对于静态资源的那就是各种图片,对于会动的资源可以考虑直接做成swf。制作成swf的美术资源又可以分为两种:一种是直接将关键帧罗列在主时间轴上,那么当程序使用Loader类加载完swf文件后,就可以直接addChild在显示列表上;另一种是将美术资源封装成影片剪辑(MovieClip),并为AS3导出类,这样在程序中可以用类似new XXX的方式将美术资源创建出来。

弊端
然而,这种使用swf的方式有一个非常大的弊端,就是会重复创建位图,导致内存浪费。比如,你使用Flash CS5制作了一个swf文件,在主时间轴上放置了一个图片。那么,当你每次使用Loader加载这个swf文件的时候,实际上会创建出很多个位图实例,非常占用内存。Flash自身有一个BitmapData类是用来处理这种情况的,具体用法就是多个DisplayObject共用一个BitmapData,做到位图资源共享,减少内存开销。但是,你需要手动指定哪几个DisplayObject需要共用BitmapData。像上述这种情况,两次加载同一个swf文件,Flash并不会自动为我们共享使用其中的位图资源。

无标题 多次装载一个含有桌面壁纸图片的swf文件后,内存的使用情况

Flash的这种做法可以理解,毕竟Adobe认为绝大多数Flash中使用的美术资源都是矢量图而不是位图。但是,对于页游来说,基本上所有的美术资源都是位图序列帧动画。比如一个场景中有10个模型相同的玩家角色,如果存在10份序列帧动画的位图副本,那是巨大的浪费。
继续阅读