不用虚函数机制实现运行时多态

今天在豆瓣看到一个好友讨论构造函数、运算符重载等等相关概念。于是想到C++里面实现运行时多态只能用虚函数机制吗?一直以来从各种学习材料上都是这么学的:提到多态要知道有编译时和运行时之分;运行时多态和晚期联编要用到虚函数机制……等等,好像这俩概念是连体的一样。实际上C++的多态机制只是用vtable和虚函数帮我们做了很多事情而已,不用虚函数,也可以实现多态——当然,这样一来有些功能可能就用不了了,比如我曾经在概念上犯过SB的dynamic_cast。

那么要怎么实现呢?假设手头有两个类,Base和从它继承出来的Derive,两者都定义了名为Foo()的成员函数。我们期望下面的调用可以走到Derive的版本里面:

Base* d = new Derive();
d->Foo();

最最简单的思路:

(static_cast(d))->Foo();

怎么样,确实达到了要求,只不过……有些犯规的感觉。

那么换个思路,利用函数指针:

class Base
{
    public:
    void Foo()
    {
        if ( _pVFunc == NULL )
            cout<<"Base::Foo"<

略寒碜,而且那个_pVFunc语义非常不明确,美化一下:

class Base
{
    public:
    typedef void (Base::*V_FUNC)();
    void Foo() { (_caller->*_foo)(); }
    Base() { SetFunc( this, &Base::DoFoo ); }
    protected:
    void SetFunc( Base* caller, V_FUNC func) { _caller = caller; _foo = func; }
    Base* _caller;
    V_FUNC _foo;
    private:
    void DoFoo() { cout<<"Base::Foo"<

等等,这似乎完全不算是美化啊,依然寒碜到家——只是调用者和函数的关系更加明确了。指向成员函数的指针这种东东可读性真的不够好。目前为止穷尽我的脑细胞也就能想到上面这两类(如果第一种也算)方法来。用函数指针实现的版本虽然调用上令人满意,但实现上问题实在太多:指针类型要跟着函数原型走,新增一种其他参数、返回值的函数就要重新写一个;和类型绑定,无法扩展;SetFunc丑陋无比。

于是放狗发现StackOverflow上面有个帖子Can I get polymorphic behavior without using virtual functions?专门讨论这个话题。里面我所考虑的这些方法都有。

最值得注意的当然是James McNellis列出的两个方案,第一种也是和类型绑定,用了union存储函数指针,并且将cast部分专门提了一个wrapper类出来,总体来说可读性和实用性也就那样(他提到不能用std::function,因为这东西也是用虚函数实现)。但第二种非常cooool,利用宏定义和函数重载,加上boost的特性模拟了一个vtable出来,至于型别转换、函数映射都隐藏得非常好,使用的类只要在定义中一两行代码就可以上路了。

用《收获祭》学日语 1029

开始用西泽保彦的《收获祭》学日语了。作为西泽老师的铁杆粉丝,书买回来总不能吃灰吧。当然,作为买国内版书籍都得等降到7折才出手的无产阶级来说,虽然很喜欢单行本的封面,但还是买了文库本。除了价格上的考虑外,便于携带也是我一直坚持买文库本的原因。这本的文库本封面是下面这样:

单行本则是Giuseppe Arcimboldo的作品,漂亮!

好了,开始总结到目前为止学习到的新知识。

动词

  • 【難儀する】苦恼;困窘
  • 【造作する・ぞうさく】修建
  • 【見初める・みそめる】一见钟情
  • 【舌打ち】砸吧嘴
  • 【弛む・たるむ】
  • 【算段する】筹措(资金);安排事情
  • 【卸す・おろす】批发
  • 【うんざりする】厌烦
  • 【淀む・よどむ】拥塞;沉淀
  • 【おさらば】告辞
  • 【煽る・あおる】煽动/激发(心理、情绪);催促(马匹);(风)吹动
  • 【もやもやする】朦胧;隔阂(心の中のもやもやが晴れない);混乱
  • 【受け継ぐ】继承
  • 【目配せする】递眼色
  • 【頷く・うなずく】点头;首肯
  • 【言い繕う・いいつくろう】掩饰,遮掩
  • 【左遷する・させん】降职
  • 【追い抜く】追赶上
  • 【渡航・とこう】出国;渡海
  • 【くわえる】叼着,衔着
  • 【老い込む・おいこむ】老去
  • 【懲りる・こりる】吃过苦头不敢再尝试
  • 【波打つ】起浪;波动
  • 【波立つ】起浪;不平静(波立つ胸を抑える)
  • 【頓着・とんちゃく】在意
  • 【めげる】畏惧(年にめげない);垂头丧气
  • 【受講・じゅこう】听讲

名词

  • 【造作・ぞうさ】麻烦;费事
  • 【造作・ぞうさく】面容;装修
  • 【頬骨・ほおぼね】颧骨
  • 【厄介】寄宿的人
  • 【強面・こわもて】可怕的面孔
  • 【やり場】放东西的地方
  • 【男勝り・おとこまさり】巾帼英雄
  • 【蝋燭・ろうそく】蜡烛
  • 【教鞭・きょうべん】教鞭(を執る)
  • 【僻地・へきち】偏僻的地方
  • 【割烹着・かっぽうぎ】做饭时穿的外衣
  • 【良妻賢母・りょうさいけんぼ】贤妻良母
  • 【陰口・かげぐち】背地里说坏话(をきく、をたたく)
  • 【風貌・ふうぼう】风貌
  • 【粘り腰】坚韧不拔
  • 【剃り跡・そりあと】刮胡子后的印记
  • 【屈辱・くつじょく】屈辱
  • 【碧眼・へきがん】碧眼

形容词・副词

  • 【満杯・まんぱい】满满的
  • 【難儀・なんぎ】困难的
  • 【憎憎しい・にくにくしい】让人讨厌的
  • 【厄介・やっかい】麻烦的
  • 【ぞろぞろ】一个接一个的
  • 【くっきり】显眼地
  • 【ひっそり】默默地;寂静无声
  • 【耳障り】刺耳的
  • 【大分・だいぶ】相当多的;非常地
  • 【切実】迫切;切实
  • 【賑やか・にぎやか】热闹;开朗

句型

  • 【~に限らず、~】不仅是~,~
  • 【~とは対照的に、~】和~形成对照,~
  • 【~譲りの~】从~继承下来的~
  • 【~称して】被称为~

日语学习总结 2012.10

以后定期(具体“期”是多少还没定)把在lang-8上的学习过程总结下来。一般是来写短文时候学到的生词和来自批改者的的修改,也有从评论中提取的新内容。

词汇

【エアロビクス】:有氧运动
【冷え込む・ひえこむ】:  气温骤降;(身体)着凉
【読破する・どくは】:读完
【噛み締める・かみしめる】:咬住;揣摩,推敲
【決して・けっして】:绝对(不)
【さも】:非常,很;好像,那样
【イラストレーター】:画师
【吸い込む・すいこむ】:吸入
【ふりかけ】:撒在米饭上的调味品
【拘る・こだわる】:拘泥于~;讲究~
【維持する・いじ】:维持
【生粋・きっすい】:地道的(但一般口语不用)
【繁殖する・はんしょく】:繁殖
【迷路・めいろ】:迷宫
【予め・あらかじめ】:预先,事前
【割り込む・わりこむ】:挤进去,加塞
【遮る・さえぎる】:挡住
【押し退ける・おしのける】:推开
【ぶつける】:扔,摔,撞
【下車する・げしゃ】:下车
【いまだ】:至今
【解明する・かいめい】:清楚,了解
【書き換える・かきかえる】:重写;把~改为~;过户
【無駄話・むだばなし】:闲话,闲聊
【四辻 四つ角】:十字路口
【経つ・たつ】:(时光)流逝
【同窓・どうそう】:同窗
【掲載する・けいさい】:
【むっとする】:怒上心头;闷得慌
【むかむかする】:生气,火冒三丈;作呕
【装丁する・そうてい】:装订

短语

【関連付ける】
【連絡を取る】
【決まり文句】:惯用语
【いつも見ている~】:经常去的~
【わりを食う】:吃亏
【話に乗る】:听信(传言、谣言)
【メモを取る】:记笔记
【頭をフル回転する】:绞尽脑汁
【飛び石】:不连续的(地)

句法

【~し通す】:做完~
【~し終える】:做完~
【~のなさそう】:似乎没有~
【ただ~に過ぎない】:不过是当作~
【~を降りて~】:放弃~而~
【~に従って】和【~と伴に】:两者意思接近。但前者多用于表达主观化的结论。后者多用于陈述事实。
【さもないと~】:不然的话~
【お手上げ】:束手无策
【なぜならば/なぜかというと~だからだ】:谁知道竟然~
【~かのような感じがしてしまう】:不是~的感觉吗?
【そうじゃなくて~】:礼貌地否定对方的说法,转换相关话题
【主だった】:主要是~
【~を言うのは、早すぎるかもしれない】:认定~的话未免太草率。

有关时态

对于时态的把握一直不太好。什么时候用持续性质的「いてる」?什么时候用过去时?感觉一直有点糊涂。只能对比一下自己犯过的错误认真记下来了。
宗像教授在大学教授考古学,专攻“铁器”。
(X)宗像教授大学で考古学を教えて「鉄器」を専攻した
(O)宗像教授大学で考古学を教えていて「鉄器」を専攻した

实际上我过去在学校前的十字路口卖报纸。
(X)俺は実は学校の前の四辻で新聞を売った。
(O)俺は実は学校の前の四辻で新聞を売っていた。

我在这个学校上过一年学
(X)僕は一年間にこの学校に通った。
(O)僕は一年間にこの学校に通ってました。

近似词

【売店】:小卖部
【コンビニ】:便利店,类似物美24小时、7-11、famima那种
【感心】:谦让语。用于上级对下级表现的评价
【感服】:用于平级或者对上级者。
http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1210164907

lang-8是个学语言的好地方

偶然的机会在论坛上看到有人说在lang-8上学外语。去看了一下,似乎之前浏览过但没怎么在意。简单说lang-8就是一个“交换语言”的站点,可以用自己正在学习的语言写文章,然后由母语使用者修改;反过来自己也可以去修改别人的文章。

lang-8是由日本人建立的,所以日本人不少。据他们的统计说现在外国人已经占了7成。所以基本上想学什么语言都没问题。一般来说,英语、日语和中文会得到最多最快的修改/批改建议。写了文章后,网站会自动根据句号进行分句,然后一行行列出供人修改。个人经验来讲,写完后大概十几二十分钟就会有人来改了。当然,批改是没有报酬的,文章作者可以根据自己得到帮助的程度给批改人加星,从一到五。

不管是什么社区,都会有相关的礼仪,个人总结了一下lang-8的:

  • 批改时候尽量利用字体颜色的变化标明。如果有复杂的地方说明一下更好。
  • 在自己的文章里面,最好用文章的语言来和别人对话和交流。这样对自己增进语言熟悉程度也有帮助。
  • 而在批改别人的文章时,也要用他所使用的语言。比如去帮别人改中文,那么除非对方说“不太看得懂”否则都用中文。
  • 得到别人的批改后,留言感谢是必要的,评分也是必要的。

但lang-8也存在一些问题,比如母语使用者本身可能出现错误或者就有错误用法。lang-8上的用户水平参差不齐,就我得到的批改情况来看,有些偏向口语化甚至会有非正规文法出现;有些则是由貌似日本教师的用户批改,将我的随笔给改成了专业论文(很汗,但修改后真的超专业)。这一点则可以通过多人批改后对比来避免,用户多用点心就行了。而一些对于非热门语言,母语使用者相互之间的“配对”可能性就不高——例如中文-德语相对于中文-日语就少得多得多——那么得文章到浏览和批改的机会也就少很多。所以我最近好几篇德语习作都是由学各种其他语言的德语使用者帮着批改的。

lang-8其实不仅能学语言,还可以了解很多风土人情。比如有篇随笔里面我好奇日本地铁电车那么挤,那么下车时候也像我们一样问“您下吗”吗?然后得到了多个答案都是不问别人,而是说着“我要下了(降りま~す)”就一边挤出去了。来过中国的日本人则在地铁上被人问是否下车时候吓了一跳。这类信息交换,很有趣,甚至可以展开来做点研究。

我的页面:http://lang-8.com/490846,大家如果也在上面写文章交流的话欢迎加我。

用Behavior在WP7平台上转换HTML Tag效果

之前的项目需要从服务器获取一段HTML内容,将其效果显示在手机端。Android和iOS都有比较轻松的方法实现此效果,但WP7的RichText比较挫,挫到什么程度?不仅在后台生成内容需要new一大堆Run、Paragraph之类的特定元素,连直接绑定属性都必须用特殊的XAML tags。所以从一开始压根儿就没想着能直接转换。由于要处理的HTML Tags不算很多,所以采用了正则表达式匹配后替换Tag内内容为特定元素的方法。

简单说来就是将某Tag和它后面(可能存在的)普通文本作为“一对”元素进行处理,根据Regex::Matches()匹配出来的一个个Match去找它后面的普通文本,然后分别按照指定的颜色和普通颜色生成两截文字,添加到RichText中。

而单纯绑定RichText的内容是行不通的(见上面的链接),所以用了Behavior进行文本到特定元素的处理,这样将需要绑定的Property丢给Behavior就可以了。

效果类似于:

Demo下载。只演示了识别Font后根据它指定的颜色生成对应文本的效果,由于项目还在进行,没法把解析更多Tag的代码放出来,但思路基本是一致的。