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

今天在豆瓣看到一个好友讨论构造函数、运算符重载等等相关概念。于是想到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的作品,漂亮!

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

动词

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

名词

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

形容词・副词

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

句型

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