??xml version="1.0" encoding="utf-8" standalone="yes"?>久久久国产一区二区三区,性做久久久久久久久浪潮,精品综合久久久久久97http://www.shnenglu.com/huaxiazhihuo/zh-cnTue, 06 May 2025 17:43:29 GMTTue, 06 May 2025 17:43:29 GMT60stringcȝ设计http://www.shnenglu.com/huaxiazhihuo/archive/2018/05/26/215679.html华夏之火华夏之火Sat, 26 May 2018 03:51:00 GMThttp://www.shnenglu.com/huaxiazhihuo/archive/2018/05/26/215679.htmlhttp://www.shnenglu.com/huaxiazhihuo/comments/215679.htmlhttp://www.shnenglu.com/huaxiazhihuo/archive/2018/05/26/215679.html#Feedback0http://www.shnenglu.com/huaxiazhihuo/comments/commentRss/215679.htmlhttp://www.shnenglu.com/huaxiazhihuo/services/trackbacks/215679.htmlStringcȝ设计一炚w不容易,先不?/span>C++Q那怕是其他语言Q在面对string的时候,一不小心也会掉坑,好比javaQ好?/span>C#Q一开始假?/span>utf16是定长编码,后来Unicode发展C个字节就装不下一个码位,字符串在java下,有点尴了。就是昧着良心?/span>utf32~码Q码元与码位l于一一对应了,也会遇到物理字符与逻辑字符不对应的时候,好像有些语言的字W要用两?/span>unicode值来表示Q很奇怪)Q有些语a的一个小写字W对应着好几个大写字W。即便是字符串选定了一U编码方式,始终q是要解决与其他~码的交互问题,q些交互接口也不Ҏ设计。另外,每次从长字符串中截取字符串都要重?/span>new出来一条新的字W串Q难免有一点点费Q当Ӟ现在计算机性能q剩Q这Ua是强q症?/span>

而到?/span>c++下,设计字符串所遇到的问题,p比想象中复杂Q无中生有的又凭I多出来很多不必要的要求Q内存资源管理(q个?/span>C++几乎是无解)Q异常安全(往字符串添加新内容Q假如内存分配失败,必须保持原有值的完整性)Q还有性能要求Q截取字W串避免生成新的字符Ԍ。很多很多的要求Q导致语a层面上压根就没法也不可能提供原生的字W串支持Q而这一点上又引出来新的问题Q代码里面,逻辑意义上看Q就不止存在一U字W串cd。好在,?/span>C++拥有丰富多彩?/span>featureQ应该以实现字W串cd了,q也是大C++的设计哲学,既然语言上没法实现的东西Q就提供用以支持q种东西?/span>featureQ用戯怎么实现怎么实现Q选择权交到用h里?/span>

所以,C++的库要怎么做出来一?/span>stringQ这道菜的味道如何,很让h好奇。一路考察下来Q让人大跌眼镜,竟然没有一?/span>c++库能提供品质优良字符Ԍ 其抽象充光也就是比字符数组好一点点Q完全就没有Unicode~码的抽象?/span>Stl的字W串更让人发指,竟然有几个模板参敎ͼ本来多类型的字符串问题就更是雪上加霜了,另外stl?/span>stringq不能作?/span>dll函数的参数类型。其实,很多时候,猿猴的要求真的不高,只要求一U?/span>utf8~码?/span>stringQ带有格式化Q还有一?/span>splitQ?/span>trimQ?/span>FindOneOfQ?/span>toupper{常用字W串处理的操作就行了Q只可惜Q没有一?/span>c++库能基本满q样的基本要求。其实,q些要求Q具体到C++下,要基本满I也的很困难?/span>

除了c++Q很多语a?/span>stringcd都是原子属性,一?/span>string|但凡一炚w吹草动,都要生成新的string|原有的值必M持不变。此外,其官方也提供了类gStringBuffer或?/span>StringBuilder用以构造很长很长,以I补这U动不动q成新String的性能问题。这两种cd泾渭分明。?/span>c++?/span>stringQ似乎是把这两种cdp合在一块了Q由此带来语义上的不清晰Q也造成很多不必要的ȝQ因为绝大多数场合下Q只需要?/span>string的原子属性,可变?/span>string只是用来保存字符~冲而已。知道吗Q?/span>stl?/span>string有一癑֤个成员函敎ͼ很多都是不必要的重蝲Q不q是Z避免字符串的复制而已?/span>

所以,首先要对只读?/span>string做抽象,也即?/span>string_viewQ只需两个成员字段Q字W串的v始地址以及~冲长度Qƈ且不要求?/span>0l束Q它有一个很好的Ҏ,字符串的M一部分Q也都是字符Ԍ甚至Q必要时Q一个字W,通过取地址Q也可以看做是长度ؓ1?/span>string_view。Q何连l的内存字符块,都可以看做是string_view。其不必涉及内存的分配,昑־非常的轻量Q可以在E序中到处用,只需注意到字W缓冲的生命周期Q就不必担心会引来什么问题。在string_view上,可以?/span>trimQ比较,查找Q反向查扄操作Q除了读取单个字节的q代器,q提供两套P代器Q用以取?/span>unicode码位|uin32Q,和用以访问逻辑字符Q其g?/span>stirng_view?/span>

剩下来就是可写可修改?/span>stringQ要求以0l束Q也xstl?/span>stringQ因为很多函数都?/span>string_view上,所以这里基本上都只是插入、添加、删除、替换的操作Q要注意的是Q中括号操作W不能返回字W引用,因ؓ那样完全没有M意义Q就是保留中括可回字W|意义也很?/span>Trim、查找、比较等操作Q必通过其成员函?/span>view来返回代表自qstring_view?/span>String的很多成员函敎ͼ大多数参数类型就?/span>string_viewQ因此也没有像是?/span>stl下垃?/span>string的那么多׃八糟的重载。很明的设计Q性能与简单的良好l一Q不知ؓ何,stl要到c++17的时候,才会加入stirng_viewq么重要的类型,即便是如此,stl?/span>string既有代码已成定局Q也没办法用string_view来简化它的一癑֤个的成员函数?/span>



华夏之火 2018-05-26 11:51 发表评论
]]>
U8String的重构体?/title><link>http://www.shnenglu.com/huaxiazhihuo/archive/2018/05/22/215672.html</link><dc:creator>华夏之火</dc:creator><author>华夏之火</author><pubDate>Tue, 22 May 2018 09:10:00 GMT</pubDate><guid>http://www.shnenglu.com/huaxiazhihuo/archive/2018/05/22/215672.html</guid><wfw:comment>http://www.shnenglu.com/huaxiazhihuo/comments/215672.html</wfw:comment><comments>http://www.shnenglu.com/huaxiazhihuo/archive/2018/05/22/215672.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/huaxiazhihuo/comments/commentRss/215672.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/huaxiazhihuo/services/trackbacks/215672.html</trackback:ping><description><![CDATA[<div> <p style="text-indent:21.0pt"><span style="font-family:宋体;">q两q来在写</span>C++<span style="font-family:宋体;">的运行时环境Q反、运行时cd信息、内存管理、ƈ行、字W串、协E?/span>ORM<span style="font-family:宋体;">{等Q基本上重写了一?/span><span style="font-family:宋体;">标准库以及运行库。对于在</span>c++<span style="font-family:宋体;">下用字W串Q深有体会。一开始呕心沥血Q殚_虑,支持多种~码方式Q?/span>Utf8<span style="font-family:宋体;">?/span>Utf7<span style="font-family:宋体;">?/span>GB2312<span style="font-family:宋体;">?/span>Utf16LE<span style="font-family:宋体;">Q?/span>Utf16BE<span style="font-family:宋体;">{)的字W串cdQ以及在此之上的对这些字W串提供格式化、字W串解析?/span>json<span style="font-family:宋体;">?/span>xml<span style="font-family:宋体;">、文件读?/span>BOM<span style="font-family:宋体;">{等功能Q必L认,?/span>C++<span style="font-family:宋体;">真是变态,像是q样变态无聊的概念都可以支持,q可以实现得很好Q用h实也方ѝ可是,每次面字符串操作的时候,都会心里发毛Q都会嘀咕此时此刻,U结的是哪门子的~码Q也搞得很多代码必须?/span>template<span style="font-family:宋体;">的Ş式,攑֜头文件上Q不攑֜头文Ӟ必L象出来一个通用的动态字W串cdQ代表Q意编码的一U字W串cdQ代码里面引入各U各栯造的复杂性。终于受不了啦,最后搞成统一?/span>utf8<span style="font-family:宋体;">~码Q重构了几千行代码(十几个文ӞQ然后,整个字符串世界终于清静了Q接?/span>api<span style="font-family:宋体;">设计什么的Q也一下子清爽了很多。整个程序内部,应该只使用同一U编码的字符丌Ӏ?/span>stl<span style="font-family:宋体;">的带有多个模板的</span>string<span style="font-family:宋体;">设计Q就是无病呻吟,画蛇添?/span></p> <p style="text-indent:21.0pt"><span style="font-family:宋体;">Z么选择</span>Utf8<span style="font-family:宋体;">~码Q首先,?/span>unicode<span style="font-family:宋体;">~码的字W串是不能考虑的;其次Q?/span>utf16<span style="font-family:宋体;">也是变长的编码方式,而且q有大小端的区别Q所以也不能考虑Q?/span>utf32<span style="font-family:宋体;">又太占用内存了。想来想去,l于下定军_Q?/span>utf8<span style="font-family:宋体;">直就是唯一的选择了。虽然可能有q样那样的小问题Q比如说Q纯中文文本Q?/span>utf8<span style="font-family:宋体;">占用?/span>50%<span style="font-family:宋体;">内存Q相比于</span>Utf16<span style="font-family:宋体;">Q,</span>windows<span style="font-family:宋体;">?/span>utf8<span style="font-family:宋体;">有点不友好。但其实都不是问题,也都可以解决。比如说Q?/span>windows<span style="font-family:宋体;">下,所有的涉及字符串与pȝ?/span>api<span style="font-family:宋体;">交互Q先临时转换?/span>utf16<span style="font-family:宋体;">Q然后再调用</span>api<span style="font-family:宋体;">?/span>api<span style="font-family:宋体;">的返回结果ؓ</span>utf16<span style="font-family:宋体;">Q再转换?/span>utf8<span style="font-family:宋体;">。好像有一Ҏ能上的损失Q其实没啥大不了的?/span>windows<span style="font-family:宋体;">对于多字节也是这h持的Q完全就感受不到性能上的影响。MQ?/span>utf8<span style="font-family:宋体;">直就是程序处理的唯一字符串编码?/span></p> <p style="text-indent:21.0pt"><span style="font-family:宋体;">吐槽一?/span>std<span style="font-family:宋体;">的字W串Q以及与此相关的一切概念,</span>iostream<span style="font-family:宋体;">Q?/span>locale<span style="font-family:宋体;">{等东西Q垃圾设计的典范。接口不友好Q功能弱Q而且q性能差,更关键的是其抽象上的泄漏。一整天只会在引用计数Q写时复Ӟ短字W串优化上做文章Q时间精力都不用在刀刃上?/span>C++17<span style="font-family:宋体;">l于引入</span>string_view<span style="font-family:宋体;">的类型,情况E微有些改善。由于字W串使用上不方便Q也因此损失了一大片的用P阵地一再失守。整体上Ԍ</span>stl<span style="font-family:宋体;">的设计,自然是有_ֿ的考虑Q但是,作出q些抽象的标准会上一大群的老爷子们Q大概率上讲Q应该是没有?/span>stl<span style="font-family:宋体;">正儿八经地开发工业上的代码Q臆造抽象,虑太多Q表面上看v来好像是那么一回事Q真正用h的时候,׃太对Ԍ会有q样那样的不I很不方便?/span></p> <p style="text-indent:21.0pt"><span style="font-family:宋体;">单说一?/span>U8String<span style="font-family:宋体;">的设计思\?/span>U8String<span style="font-family:宋体;">用以理字符串编码缓存的生命周期Q追加羃短替换字W串Q支持通过下标可以d字节</span>char<span style="font-family:宋体;">Q但是不支持字节写入到某个索引上的位置Q当然支持往字符串中插入</span>unicode<span style="font-family:宋体;">~码的字W。至于字W串的比较、查找?/span>Trim<span style="font-family:宋体;">、截取子字符串这些常用操作,全部压?/span>U8View<span style="font-family:宋体;">上。如?/span>U8String<span style="font-family:宋体;">要用这些,要先通过</span>view<span style="font-family:宋体;">的函敎ͼ获取自己字节~存下的视图?/span>U8View<span style="font-family:宋体;">表示一D连l的字符~码内存Q?/span>U8View<span style="font-family:宋体;">的Q意一部分也是</span>U8View<span style="font-family:宋体;">Q不要求?/span>0<span style="font-family:宋体;">l束。只要求</span>U8View<span style="font-family:宋体;">的生存周期不能比其宿主(</span>U8String<span style="font-family:宋体;">Q字W数l,</span>U8<span style="font-family:宋体;">原生字符Ԍ长命。事实上Q很?/span>api<span style="font-family:宋体;">的字W串参数Q其实只是要求ؓ</span>U8View<span style="font-family:宋体;">p了,不需要是什?/span>const string&<span style="font-family:宋体;">cd。此外,q提?/span>U8PointPtr<span style="font-family:宋体;">的指针类型,用以遍历</span>U8View<span style="font-family:宋体;">Q其取gؓ</span>unicode<span style="font-family:宋体;">~码|也就?/span>wchar_t<span style="font-family:宋体;">cd。另外,既然?/span>U8View<span style="font-family:宋体;">Q自然也有</span>ArrayView<span style="font-family:宋体;">Q代表连l内存块的Q意类型?/span></p> <p style="text-indent:21.0pt"><span style="font-family:宋体;">自然Q库中必L供格式化</span>Fmt<span style="font-family:宋体;">以及解析字符?/span>Scanf<span style="font-family:宋体;">的函数?/span>StrFmt<span style="font-family:宋体;">用以生成新的</span>U8String<span style="font-family:宋体;">Q?/span>Fmt<span style="font-family:宋体;">格式化函C传入字符串的话,将格式化结果追加到字符串后面?/span>Fmt<span style="font-family:宋体;">可以格式化数据到控制収ͼ文本文gQ日志等{输出结果上?/span>StrFmt<span style="font-family:宋体;">的实现只是简单地调用</span>Fmt<span style="font-family:宋体;">q返?/span>U8String<span style="font-family:宋体;">。有?/span>Fmt<span style="font-family:宋体;">?/span>Scanf<span style="font-family:宋体;">Q操作字W串很方便很灵zMQ同时也消除很多很多有关字符串相关的处理函数?/span>Fmt<span style="font-family:宋体;">不仅仅能格式化基本类型,自定义类型,q能格式化数l,</span>vector<span style="font-family:宋体;">Q?/span>list<span style="font-family:宋体;">Q?/span>pair<span style="font-family:宋体;">Q?/span>tuple<span style="font-family:宋体;">{模板类型的数据。库中也提供了类g</span>iostream<span style="font-family:宋体;">重蝲</span><<<span style="font-family:宋体;">?/span>>><span style="font-family:宋体;">的操作符。大</span>C++<span style="font-family:宋体;">提高?/span>feature<span style="font-family:宋体;">Q造出来的</span>string<span style="font-family:宋体;">cdQ用上的方便,一炚w不逊色于其他Q何语a的原?/span>string<span style="font-family:宋体;">cd。当Ӟ</span>std<span style="font-family:宋体;">的那?/span>string<span style="font-family:宋体;">Q简直就是废物?/span></p> <p style="text-indent:21.0pt"><span style="font-family:宋体;">不管怎么_本hq是很喜?/span>C++<span style="font-family:宋体;">的,?/span>c++<span style="font-family:宋体;">写代码很舒畅Q可比用</span>C#<span style="font-family:宋体;">?/span>haskell<span style="font-family:宋体;">?/span>lisp<span style="font-family:宋体;">?/span>scala<span style="font-family:宋体;">时要开心很多?/span>C++<span style="font-family:宋体;">发展?/span>C++11<span style="font-family:宋体;">Q基本功能也都完备了Q当Ӟ</span>C++14<span style="font-family:宋体;">?/span>C++17<span style="font-family:宋体;">自然功能更加强大Q特别是实现模板库的时候,更方便了,也确实很吸引人。自Ӟ</span>C++<span style="font-family:宋体;">也非十全十美Q也有很多的不Q比如不能自定义操作W,不提供非侵入式的成员函数Q缺乏gq求值的语言机制Q引用的修改l定Q只要不l定?/span>nullptr<span style="font-family:宋体;">好了)Q成员函数指针的无端限制。但是,世界上又哪里存在完美?/span>language<span style="font-family:宋体;">呢,特别是对于这U直接操U内存的底层语言来说。至?/span>rust<span style="font-family:宋体;">Q叫嚣着要取?/span>c++<span style="font-family:宋体;">Q就它那副特性,q远着呢?/span></p> </div><img src ="http://www.shnenglu.com/huaxiazhihuo/aggbug/215672.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/huaxiazhihuo/" target="_blank">华夏之火</a> 2018-05-22 17:10 <a href="http://www.shnenglu.com/huaxiazhihuo/archive/2018/05/22/215672.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>U有l承讨?/title><link>http://www.shnenglu.com/huaxiazhihuo/archive/2017/12/13/215423.html</link><dc:creator>华夏之火</dc:creator><author>华夏之火</author><pubDate>Wed, 13 Dec 2017 07:17:00 GMT</pubDate><guid>http://www.shnenglu.com/huaxiazhihuo/archive/2017/12/13/215423.html</guid><wfw:comment>http://www.shnenglu.com/huaxiazhihuo/comments/215423.html</wfw:comment><comments>http://www.shnenglu.com/huaxiazhihuo/archive/2017/12/13/215423.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.shnenglu.com/huaxiazhihuo/comments/commentRss/215423.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/huaxiazhihuo/services/trackbacks/215423.html</trackback:ping><description><![CDATA[<p style="text-indent:21.0pt"><span style="font-family:宋体;">大家都知道,?/span>C++<span style="font-family:宋体;">里面可以U有l承Q之后基cȝ一切,在子cM成?/span>private<span style="font-family:宋体;">的了Q不对外开放了。现在流行接口,l合优化l承Q所?/span>private<span style="font-family:宋体;">l承q玩意,日渐式微Q很久以前就很少使用了,嗯,不要?/span>private<span style="font-family:宋体;">Q就是?/span>c++<span style="font-family:宋体;">Q也是江x下。不q,存在卛_理,</span>c++<span style="font-family:宋体;">语法里面的Q何东西,都有其h|qx可以用不刎ͼ但是关键时刻用一下,实很方便,当然多数情况下,也可以其他途径来完成,但是Q就是没那么舒服?/span></p> <p style="text-indent:21.0pt"><span style="font-family:宋体;">废话׃说了Q直入正题吧?/span></p> <p style="text-indent:21.0pt"><span style="font-family:宋体;">假设Q现在有接口Q假设是</span>IUnknown<span style="font-family:宋体;">Q里面有那三个著名的U虚函数Q?/span>QueryInterface, AddRef, Release<span style="font-family:宋体;">Q好像是q三个哥俩?/span></p> <p><span style="font-family:宋体;">然后Q有一个类Q就?/span>ClassA<span style="font-family:宋体;">Q实C</span>IUnknown<span style="font-family:宋体;">接口Q其实就是?/span>IUnknown<span style="font-family:宋体;">Q也是_重写了那三个U虚函数。此外,</span>ClassA<span style="font-family:宋体;">q有一大堆自己的东西,比如</span>public<span style="font-family:宋体;">的字D|者成员函数?/span></p> <p style="text-indent:21.0pt"><span style="font-family:宋体;">现在Q有</span>ClassB<span style="font-family:宋体;">Q想Z</span>ClassA<span style="font-family:宋体;">来做一些事情,但是又不惌用户看到</span>ClassA<span style="font-family:宋体;">里面那些׃八糟的玩意,因此Q这U情况下Q用</span>private<span style="font-family:宋体;">g很合适。代码如下:</span></p> <p><span>         struct IUnknown</span></p> <p><span>         {</span></p> <p><span>         public:</span></p> <p><span>                            virtual HRESULT QueryInterface(REFIID riid,void** ppvObject) = 0;</span></p> <p><span>                            virtual ULONG AddRef() = 0;</span></p> <p><span>                            virtual ULONG Release() = 0;</span></p> <p><span>         };</span></p> <p><span>         struct ClassA : IUnknown</span></p> <p><span>         {</span></p> <p><span>                   virtual HRESULT QueryInterface(REFIID riid, void** ppvObject) override { ... }</span></p> <p><span>                   virtual ULONG AddRef() override { ... }</span></p> <p><span>                   virtual ULONG Release() override { ... }</span></p> <p><span>                   ...</span></p> <p><span>         };</span></p> <p><span>         struct ClassB : private ClassA</span></p> <p><span>         {</span></p> <p><span>                   ...</span></p> <p><span>         };</span></p> <p style="text-indent:21.0pt"><span style="font-family:宋体;">q里Q内存的使用上非常紧凑,可以_没有多余的地斏V但是,q里?/span>private<span style="font-family:宋体;">Q不仅仅?/span>private ClassA<span style="font-family:宋体;">的一切,p</span>IUnknown<span style="font-family:宋体;">也被</span>private<span style="font-family:宋体;">Q这有时候就不符合要求了Q因里意图是Q?/span>private ClassA<span style="font-family:宋体;">Q但是又?/span>public IUnknown<span style="font-family:宋体;">Q也是_对外界来_</span>ClassB<span style="font-family:宋体;">不是</span>ClassA<span style="font-family:宋体;">Q虽然其内部Z</span>ClassA<span style="font-family:宋体;">实现Q但是,又希?/span>ClassB<span style="font-family:宋体;">?/span>IUnknown<span style="font-family:宋体;">。对此,有几U解军_法,但是都不能让人满意?/span></p> <p><span style="font-family:宋体;">Ҏ</span>1<span style="font-family:宋体;">、让</span>ClassB<span style="font-family:宋体;">再次实现</span>IUnknown<span style="font-family:宋体;">接口Q如下所C:</span></p> <p><span>         struct ClassB : private ClassA, public IUnknown</span></p> <p><span>         {</span></p> <p><span>                   virtual HRESULT QueryInterface(REFIID riid, void** ppvObject) override { ... }</span></p> <p><span>                   virtual ULONG AddRef() override { ... }</span></p> <p><span>                   virtual ULONG Release() override { ... }</span></p> <p><span>         };</span></p> <p style="text-indent:21.0pt"><span style="font-family:宋体;">其好处是Q?/span>ClassB<span style="font-family:宋体;">的实例可以无~用?/span>IUnknown<span style="font-family:宋体;">的一切场合,不管是引用或者指针,</span>const<span style="font-family:宋体;">?/span>const<span style="font-family:宋体;">。但是,代h也是很大的,首先要针?/span>IUnknown<span style="font-family:宋体;">的每个虚函数Q都要一一手写Q再ơ{发给</span>private<span style="font-family:宋体;">的基c,其次Q?/span>ClassB<span style="font-family:宋体;">?/span>ClassA<span style="font-family:宋体;">多了一个虚函数表指针,大小比原来多了一个指针的大小Q这׃是零惩罚了,q是最不该?/span></p> <p><span style="font-family:宋体;">Ҏ</span>2<span style="font-family:宋体;">Q还是保持私有承,再在</span>ClassB<span style="font-family:宋体;">中添加几个函敎ͼ用以q回</span>IUnknown<span style="font-family:宋体;">Q代码如?/span></p> <p><span>         struct ClassB : private ClassA</span></p> <p><span>         {</span></p> <p><span>                   //</span><span style="font-family:宋体;">也可?/span><span>using ClassA</span><span style="font-family:宋体;">的三?/span>IUnknown<span style="font-family:宋体;">里面的函?/span></p> <p><span>                   const IUnknown* GetUnknown()const { return this; }</span></p> <p><span>                   IUnknown* GetUnknown()const { return this; }</span></p> <p><span>         };</span></p> <p style="text-indent:21.0pt"><span style="font-family:宋体;">避开了方?/span>1<span style="font-family:宋体;">的不I但是׃能无~用?/span>IUnknown<span style="font-family:宋体;">下,每次使用必须调用一?/span>GetUnknown()<span style="font-family:宋体;">Q对于引用的情况下,q必d多一个星?/span>*<span style="font-family:宋体;">Q也是挺不方便的。对了,q里qd了类型函数重载,也即?/span>operator IUnknown<span style="font-family:宋体;">Q编译器也拒l将</span>ClassB<span style="font-family:宋体;">无缝转换?/span>IUnknown<span style="font-family:宋体;">?/span></p> <p><span style="font-family:宋体;">Ҏ</span>3<span style="font-family:宋体;">Q用包含Q不用私有ѝ如下:</span></p> <p><span>         struct ClassB</span></p> <p><span>         {</span></p> <p><span>                   ClassA mA;</span></p> <p><span>                   operator const IUnknown&()const { return *this; }</span></p> <p><span>                   operator IUnknown&() { return *this; }</span></p> <p><span>         };</span></p> <p style="text-indent:21.0pt"><span style="font-family:宋体;">q样子,</span>ClassB<span style="font-family:宋体;">的实例可以无~用?/span>IUnknown<span style="font-family:宋体;">引用下的情况。对于指针的话,可以仉K方?/span>2<span style="font-family:宋体;">那样子,写两个函数进行调用。貌似综合v来,Ҏ</span>3<span style="font-family:宋体;">的整体分数最高?/span></p> <p style="text-indent:21.0pt"><span style="font-family:宋体;">׃言Q更偏向于,直接p</span><span>ClassB public</span><span style="font-family:宋体;">l承</span>ClassA<span style="font-family:宋体;">好了Q少了那么多鬼怪,虽然出现很多不必要的函数Q其实也没什么不好?/span></p><img src ="http://www.shnenglu.com/huaxiazhihuo/aggbug/215423.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/huaxiazhihuo/" target="_blank">华夏之火</a> 2017-12-13 15:17 <a href="http://www.shnenglu.com/huaxiazhihuo/archive/2017/12/13/215423.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>回顾C++http://www.shnenglu.com/huaxiazhihuo/archive/2017/07/15/215111.html华夏之火华夏之火Sat, 15 Jul 2017 12:07:00 GMThttp://www.shnenglu.com/huaxiazhihuo/archive/2017/07/15/215111.htmlhttp://www.shnenglu.com/huaxiazhihuo/comments/215111.htmlhttp://www.shnenglu.com/huaxiazhihuo/archive/2017/07/15/215111.html#Feedback2http://www.shnenglu.com/huaxiazhihuo/comments/commentRss/215111.htmlhttp://www.shnenglu.com/huaxiazhihuo/services/trackbacks/215111.html本h对于c++的认识,多年下来Q经历了以下几个阶段Q?/span>

1?nbsp;c++很好很强大,盲目q求q行性能Q简直巴普洛夫条件反,贡献了一大坨垃圾代码Q?/span>

2?nbsp;c++的面向对象对持很垃圾Q什么鬼Q代码很Ҏp合Q于是迷上对?/span>+消息发送的面向对象Q?/span>

3?nbsp;c++太复杂了Q?/span>template太抽象,天外飞仙Q搞不懂Q二q制复用又差。整?/span>c++是垃圾Q简直程序设计语a里面的|c,C语言多好啊,y_致单清晎ͼ

4?nbsp;使用其他语言做开发,java?/span>C#?/span>F#?/span>elisp?/span>scheme?/span>python?/span>haskell?/span>javascript?/span>php{等一大坨语言Q感概每一U语a都比垃圾C++不要好太多,发誓不再?/span>c++写哪怕一行的代码Q?/span>

5?nbsp;某一天,H然有点理解了这U语aQ一切变得清CQ原?/span>c++也相当不错,也可以做一些事情,看开之后Q感觉开发效率也跟上来了Q做同样的事情,?/span>c++实现不会?/span>C#?/span>python{慢?/span>

相比于其他语aQ?/span>c++的独特优势在?/span>

预编译期的伪囄完备Q这一点,好多语言q是有的Qƈ且更好,比如rustQ?/span>scheme

~译期间?/span>C++是功能完备的解释器,其输出结果是正常q行?/span>c++代码Q结合宏Q可以制造很多其他语a必须在语法层面上支持的语法糖。这个解释器的奇妙之处在于它q行于编译期Q一旦错误的模板代码要进入运行期Q就会出现编译错误,而不需要进入运行时的代码,即便天大错误Q也都不要紧Q而一旦这D代码要q入q行Ӟ那么模板错误逃不q编译期解释器的法眼?/span>

生成各种内存布局的便利语法糖和自q内存操控Q不同类型的对象Q只要其内存布局一_通过强制转换Q就可按同一cd来处理,q一点作死能力,l不被有gc的语a支持。内存的无节操玩弄,l合templateQ分分钟p仿真出来其他必须语言层面上提供的数据l构Q类型安全、运行性能、易用性,一炚w不逊色Q好?/span>stringQ委托,元组Q列表,可空cdQ?/span>

C++的专有特性,raii、多l承和全局变量。特别是全局变量Q结合它的构造函数特点和cd推导Q所能玩出来的丰富新花样Q其他语a很难做到。全局变量是连接运行期和编译期的桥梁。如果没有全局变量Q本座应该不会再ơ对c++产生热情。奇怪的是,至今为止Q?/span>c++的基库都不怎么挖掘全局变量的潜能。当Ӟ对全局变量的用,肯定是把它当做常量来用,全局变量有唯一的内存地址Q就起到原子的作用,但它又可打包了丰富的静态类型信息?/span>

以上的独特,造就?/span>c++层出不穷的新意,而卓的q行性能Q只是其微不道的优炏V虽然说Q语a不重要,思想才重要,软g架构才重要,但是c++所能承载的思想Q以及其到达的抽象高度,的确q的大大降低框架的复杂性,诚然Q?/span>c++的基库开发要面无穷无尽的细节纠l,其实Q这也反映了c++~译器掌控细节的能力Q因此,我们又可以让~译器自动完成很多很多细节重复,从而大q度地减M码数量,q无损其q行性能。又׃c++完备强大的静态类型特性,在用动态语a风格的简z来~写代码的同Ӟ又无损其快速方便地代码重构。笔者的基础库项目,几十ơ大规模的重构,借助单元试Q保证了重构利快速的完成Q深?/span>c++在重构上的便利,q些代码Q包括不?/span>1千行却功能完整的xml库(q支持对象与xml数据的直接互相{换)Q不?/span>1千行却一炚w不逊色?/span>boost?/span>spiritl合子解释器Q编译速度却快了很多,语法上简z很多,更能方便地解释各U语法)Q才1千多行的异步io框架Q输入输出,文g操作Q数据库Q协E等代码都简z异常,所有这些代码都支持动态库上的二进制复用,让h很惊诧于c++的光怪陆ȝ强大?/span>

当然Q?/span>c++的缺陷也震撼人心Q?/span>

1?nbsp;语言Ҏ太q繁杂抽象微妙,比如template、多l承、运符重蝲、类型{换、兼Ҏ考虑的很多糟p语aҎ,所以对使用者的节制力要求很高,要求他们时刻清楚自己在干什么,琐碎上的思考太多;

2?nbsp;~Zl一的二q制标准Q基库都用源代码的Ş式共享,q让原本龟速的~译速度更加Co人大大感动;

3?nbsp;~Z高标准的基础库,stl?/span>boost更在某些技术运用的展示上更起到很坏的媄响;

4?nbsp;~Z某些延迟求值的机制Q缺乏必要的函数式语a机制Q所?/span>c++始终无法成为堂堂正正的C化高U语aQ?/span>

p样吧?/span>



华夏之火 2017-07-15 20:07 发表评论
]]>
C++的非侵入式接?/title><link>http://www.shnenglu.com/huaxiazhihuo/archive/2017/07/15/215110.html</link><dc:creator>华夏之火</dc:creator><author>华夏之火</author><pubDate>Sat, 15 Jul 2017 09:01:00 GMT</pubDate><guid>http://www.shnenglu.com/huaxiazhihuo/archive/2017/07/15/215110.html</guid><wfw:comment>http://www.shnenglu.com/huaxiazhihuo/comments/215110.html</wfw:comment><comments>http://www.shnenglu.com/huaxiazhihuo/archive/2017/07/15/215110.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.shnenglu.com/huaxiazhihuo/comments/commentRss/215110.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/huaxiazhihuo/services/trackbacks/215110.html</trackback:ping><description><![CDATA[<p><span style="font-family:宋体;">l于写到</span>c++<span style="font-family:宋体;">的非侵入式接口了Q兴奋,开心,失望Q解脱,</span>…… <span style="font-family:宋体;">。在搞了q么多的面向对象U普之后Q本Z已经开始不耐烦Q至此,不想做太多阐q?/span></p> <p><span style="font-family:宋体;">虽然Q很早就清楚怎么?/span>c++<span style="font-family:宋体;">下搞非R入式接口Q但是,整个框架代码Q重构了十几ơ之后,才终于满意。支持给基本cdd接口Q好?/span>int<span style="font-family:宋体;">Q?/span>char<span style="font-family:宋体;">Q?/span>const char*<span style="font-family:宋体;">Q?/span>double<span style="font-family:宋体;">Q支持泛型,好比</span>vector<span style="font-family:宋体;">Q?/span>list<span style="font-family:宋体;">Q支持承,基类实现的接口,表示子类也承了对该接口的实玎ͼ而且子类也可以拒l基cȝ接口Q好比鸭子拒l基c鸟c?#8220;会飞”Q编译时报错Q支持接口组合;……Q但是,q里仅仅单介l其原理Qƈ不涉及C++中各U变态细节的处理QC++中,但凡是要正儿八经的稍微做Ҏ事,p面无穷无尽的细节纠l?/span></p> <p><span style="font-family:宋体;">先看看其使用例子Q?/span></p> <p>1<span style="font-family:宋体;">、自然是定义一个接口:取之于真实代码片D?/span></p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">    </span><span style="color: #0000FF; ">struct</span><span style="color: #000000; "> IFormatble<br />    {<br /><div>        static TypeInfo* GetTypeInfo();</div>       </span><span style="color: #0000FF; ">virtual</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">void</span><span style="color: #000000; "> Format(TextWriter</span><span style="color: #000000; ">&</span><span style="color: #000000; "> stream, </span><span style="color: #0000FF; ">const</span><span style="color: #000000; "> FormatInfo</span><span style="color: #000000; ">&</span><span style="color: #000000; "> info) </span><span style="color: #000000; ">=</span><span style="color: #000000; "> </span><span style="color: #000000; ">0</span><span style="color: #000000; ">;<br />        </span><span style="color: #0000FF; ">virtual</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">bool</span><span style="color: #000000; "> Parse(TextReader</span><span style="color: #000000; ">&</span><span style="color: #000000; "> stream, </span><span style="color: #0000FF; ">const</span><span style="color: #000000; "> FormatInfo</span><span style="color: #000000; ">&</span><span style="color: #000000; "> info)<br />        {<br />            PPNotImplement();<br />        }<br />    };<br /></span></div><p><span style="font-family: 宋体;"> </span></p><p>2<span style="font-family:宋体;">、接口的实现c,假设?/span>int<span style="font-family:宋体;">d</span>IFormatble<span style="font-family:宋体;">的接口实玎ͼ实际代码肯定不会q样对一个一个的基本cd来写实现cȝ代码。这里只是ؓ了D例说明。类的名字就随便起好啦,</span></p> <div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">    </span><span style="color: #0000FF; ">struct</span><span style="color: #000000; "> ImpIntIFormatble : IFormatble<br />    {<br />        </span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">*</span><span style="color: #000000; "> mThis;    </span><span style="color: #008000; ">//</span><span style="color: #008000; ">q一行是关键</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">        </span><span style="color: #0000FF; ">virtual</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">void</span><span style="color: #000000; "> Format(TextWriter</span><span style="color: #000000; ">&</span><span style="color: #000000; "> stream, </span><span style="color: #0000FF; ">const</span><span style="color: #000000; "> FormatInfo</span><span style="color: #000000; ">&</span><span style="color: #000000; "> info)</span><span style="color: #0000FF; ">override</span><span style="color: #000000; "><br />        {<img src="http://www.shnenglu.com/Images/dot.gif" alt="" />}<br /><br />        </span><span style="color: #0000FF; ">virtual</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">bool</span><span style="color: #000000; "> Parse(TextReader</span><span style="color: #000000; ">&</span><span style="color: #000000; "> stream, </span><span style="color: #0000FF; ">const</span><span style="color: #000000; "> FormatInfo</span><span style="color: #000000; ">&</span><span style="color: #000000; "> info)</span><span style="color: #0000FF; ">override</span><span style="color: #000000; "><br />        {<img src="http://www.shnenglu.com/Images/dot.gif" alt="" />}<br />    };</span></div><p><span style="font-family:宋体;"></span></p><p><span style="font-family:宋体;"> </span></p><p><span style="font-family:宋体;">q里的关键是Q实现类的字D被规定MQ最多只能包?/span>3<span style="font-family:宋体;">个指针成员字D,且第</span>1<span style="font-family:宋体;">个字D一定是目的cd指针Q第二是cd信息对象Q用于泛型)Q第三是额外参数Q次序不能ؕ。成员字D如果不需要用到第二第三个成员字段数据Q可以省略不写,好比q里。所有接口实现类必须遵守q样的内存布局Q?/span></p><p><span style="font-family:宋体;"><span style="font-size:10.5pt;font-family:"Calibri","sans-serif";Times New Roman";">3</span><span style="font-size:10.5pt;font-family:宋体;Times New Roman";">、装配,接口的实现c装配到现有的类上,以告诉编译器该类对于某个接口Q这里ؓ</span><span style="font-size:10.5pt;font-family:"Calibri","sans-serif";Times New Roman";">IFormatble</span><span style="font-size:10.5pt;font-family:宋体;Times New Roman";">Q的实现Q用的是W?/span><span style="font-size:10.5pt;font-family:"Calibri","sans-serif";Times New Roman";">2</span><span style="font-size:10.5pt;font-family:宋体;Times New Roman";">步的实现c?/span><span style="font-size:10.5pt;font-family:"Calibri","sans-serif";Times New Roman";">ImpIntIFormatble</span><span style="font-size: 10.5pt;font-family:宋体;Times New Roman";">Q?/span></span></p><p><span style="font-family:宋体;"><span style="font-size: 10.5pt;font-family:宋体;Times New Roman";"></span></span></p><div>PPInterfaceOf(IFormatble, int, ImpIntIFormatble);</div><p> </p><p>4<span style="font-family:宋体;">、将实现cL册到cd信息的接口实现列表中Q这一步可以省略,只是Zq行时的接口查询Q相当于</span>IUnknown<span style="font-family:宋体;">?/span>Query<span style="font-family:宋体;">。这一行代码是在全局对象的构造函C执行的,攑֜cpp源文件中</span></p><p><span style="font-family:宋体;"></span></p><div>RegisterInterfaceImp<IFormatble, int>();</div><span style="font-size:10.5pt; font-family:宋体;Times New Roman";">然后可以开开心心C用接口了Q比?br /></span><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">            </span><span style="color: #0000FF; ">int</span><span style="color: #000000; "> aa </span><span style="color: #000000; ">=</span><span style="color: #000000; "> </span><span style="color: #000000; ">20</span><span style="color: #000000; ">;<br />            TextWriter stream(<img src="http://www.shnenglu.com/Images/dot.gif" alt="" />);<br />            FormatInfo info(<img src="http://www.shnenglu.com/Images/dot.gif" alt="" />);<br />            TInterface</span><span style="color: #000000; "><</span><span style="color: #000000; ">IFormatble</span><span style="color: #000000; ">></span><span style="color: #000000; "> formatable(aa); //TInterfaceq个名字q难看,也没办法?br />            formatable</span><span style="color: #000000; ">-></span><span style="color: #000000; ">Format(stream, info);<br />            </span><span style="color: #0000FF; ">double</span><span style="color: #000000; "> dd </span><span style="color: #000000; ">=</span><span style="color: #000000; "> </span><span style="color: #000000; ">3.14</span><span style="color: #000000; ">;<br />            formatable </span><span style="color: #000000; ">=</span><span style="color: #000000; "> TInterface</span><span style="color: #000000; "><</span><span style="color: #000000; ">IFormatble</span><span style="color: #000000; ">></span><span style="color: #000000; ">(dd);    </span><span style="color: #008000; ">//</span><span style="color: #008000; ">假设double也实现IFormatble</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">            formatable</span><span style="color: #000000; ">-></span><span style="color: #000000; ">Format(stream, info);<br /></span></div><span style="font-size:10.5pt; font-family:宋体;Times New Roman";"> </span><p><span style="font-family:宋体;">是否有点奇呢?其实也没什么,不过是?/span>trait<span style="font-family:宋体;">和内存布局上做文章Q也只是用了类型运的伎俩。考察</span>ImpIntIFormatble<span style="font-family:宋体;">的内存布局Q对于普遍的</span>c++<span style="font-family:宋体;">~译器来_对象的虚函数表指针(如果存在的话Q,都放在对象的起始地址上,后面紧跟对象本n的成员数据字D,因此Q?/span>ImpIntIFormatble<span style="font-family:宋体;">的内存布局相当于,</span><span style="font-size:10.5pt; font-family:宋体;Times New Roman";"></span><br /><span style="font-size:10.5pt; font-family:宋体;Times New Roman";"></span></p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">struct</span><span style="color: #000000; "> ImpIntIFormatble<br />{<br />    </span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">*</span><span style="color: #000000; "> vtbl;<br />    </span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">*</span><span style="color: #000000;"> mThis;<br />};<br /></span></div><p> </p><p><span style="font-family:宋体;"> </span></p><p><span style="font-family:宋体;">注意Q这里已l没有承了。这是Q实C</span>IFormatble <span style="font-family:宋体;">接口?/span>ImpIntIFormatble<span style="font-family: 宋体;">对象的内存表C。因此,可以惌Q所有的接口实现cȝ内存布局都强制规定ؓ以下形式Q?/span></p> <div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">    </span><span style="color: #0000FF; ">struct</span><span style="color: #000000; "> InterfaceLayout<br />    {<br />        </span><span style="color: #0000FF; ">const</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">*</span><span style="color: #000000; "> mVtbl;<br />        </span><span style="color: #0000FF; ">const</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">*</span><span style="color: #000000; "> mThis;            </span><span style="color: #008000; ">//</span><span style="color: #008000; ">对象本n</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">        </span><span style="color: #0000FF; ">const</span><span style="color: #000000; "> TypeInfo</span><span style="color: #000000; ">*</span><span style="color: #000000; "> mTypeInfo;    </span><span style="color: #008000; ">//</span><span style="color: #008000; ">cd信息</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">        </span><span style="color: #0000FF; ">const</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">*</span><span style="color: #000000; "> mParam;    </span><span style="color: #008000; ">//</span><span style="color: #008000; ">补充参数Q一般很用?/span><span style="color: #008000; "><br /></span><span style="color: #000000; ">    };<br /></span></div><p><span style="font-family:宋体;"></span></p><p><span style="font-family: 宋体;"> </span></p><p><span style="font-family:宋体;">当然Q如果编译器的虚函数表指针不攑֜对象起始地址的话Q就没法q么玩了Q那么非侵入式接口也无从做v。然后,是</span>TInterface<span style="font-family:宋体;">了,l承?/span>InterfaceLayout</p> <div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">    template</span><span style="color: #000000; "><</span><span style="color: #000000; ">typename IT</span><span style="color: #000000; ">></span><span style="color: #000000; "><br />    </span><span style="color: #0000FF; ">struct</span><span style="color: #000000; "> TInterface : </span><span style="color: #0000FF; ">public</span><span style="color: #000000; "> InterfaceLayout<br />    {<br />        typedef IT interface_type;<br />        static_assert(is_abstract</span><span style="color: #000000; "><</span><span style="color: #000000; ">IT</span><span style="color: #000000; ">></span><span style="color: #000000; ">::value, </span><span style="color: #000000; ">"</span><span style="color: #000000; ">interface must have pure function</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br />        static_assert(</span><span style="color: #0000FF; ">sizeof</span><span style="color: #000000; ">(IT) </span><span style="color: #000000; ">==</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">sizeof</span><span style="color: #000000; ">(</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">*</span><span style="color: #000000; ">), </span><span style="color: #000000; ">"</span><span style="color: #000000; ">Can't have data</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br />    </span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">:<br />        interface_type</span><span style="color: #000000; ">*</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">operator</span><span style="color: #000000; ">-></span><span style="color: #000000; ">()</span><span style="color: #0000FF; ">const</span><span style="color: #000000; "><br />        {<br />            interface_type</span><span style="color: #000000; ">*</span><span style="color: #000000; "> result </span><span style="color: #000000; ">=</span><span style="color: #000000; "> (interface_type</span><span style="color: #000000; ">*</span><span style="color: #000000; ">)(</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">*</span><span style="color: #000000; ">)</span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">;<br />            </span><span style="color: #0000FF; ">return</span><span style="color: #000000; "> result;<br />        }<br />        <img src="http://www.shnenglu.com/Images/dot.gif" alt="" /><br />    };</span></div><p><span style="font-family:宋体;"></span></p><p><span style="font-family:宋体;"> </span></p><p><span style="font-family:宋体;">不管怎么说都好,</span>TInterface<span style="font-family:宋体;">对象的内存布局与接口实现类的内存布局一致。因此操作符</span>-><span style="font-family:宋体;">重蝲函数才可以粗暴的cd转换来顺利完成。然后构?/span>TInterface<span style="font-family:宋体;">对象的时候就是强制获?/span>ImpIntIFormatble<span style="font-family:宋体;">对象的虚函数表(也就是其起始地址的指针数据)指针赋值给</span>InterfaceLayout<span style="font-family:宋体;">?/span>mVtbl<span style="font-family:宋体;">Q进而依ơ把实际对象的指针放?/span>mThis<span style="font-family:宋体;">上,获取到类型信息对象放?/span>mTypeInfo<span style="font-family:宋体;">中,如果有必要搭?/span>mParam<span style="font-family:宋体;">Q也相应地赋倹{?/span></p> <p><span style="font-family:宋体;"> </span></p><p style="text-indent:21.0pt"><span style="font-family:宋体;">然后Q就?/span><span>template<typename Interface, typename Object>struct InterfaceOf</span><span style="font-family: 宋体;">各种特化的运用而已Q就不g提了?/span></p> <p style="text-indent:21.0pt"><span style="font-family:宋体;">׃</span>c++<span style="font-family:宋体;">?/span>abi<span style="font-family:宋体;">没有l一标准Qƈ且,</span>c++<span style="font-family:宋体;">标准也没有规定编译器必须用虚函数表来实现多态,所以,q里的奇技淫yq不能保证在所有^C都能够成立,但是Q非侵入式接口真是方便,已经是本座写</span>c++<span style="font-family:宋体;">代码的核心工P一切都围绕着非R入式接口来展开?/span> </p> <p style="text-indent: 21pt;"><span style="font-family:宋体;">原本打算长篇大论Q也只有草草收场。之后,本񔞮p放了Q会暂时d</span>cppblog<span style="font-family:宋体;">很久Q计划中的内容,消息发送,虚模板函敎ͼ字符Ԍ输入输出Q格式化Q序列化Q?/span> locale<span style="font-family:宋体;">Q全局变量Q模板表辑ּQ组合子解析器,</span>allocator<span style="font-family:宋体;">Q智能指针,E序q行Ӟ抽象工厂讉K者等模式的另cd玎ͼ以求从全新的角度上来表现</span>C++<span style="font-family:宋体;">的强大,也只能中断了?/span></p> <p><span style="font-family:宋体;"><br /></span></p><p><span style="font-family:宋体;"><br /></span></p><p><span style="font-family:宋体;"><br /></span></p><p><span style="font-family:宋体;"><br /></span></p><p><span style="font-family:宋体;"><br /></span></p><p><span style="font-family:宋体;"><br /></span></p><p><span style="font-family:宋体;"><br /></span></p><img src ="http://www.shnenglu.com/huaxiazhihuo/aggbug/215110.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/huaxiazhihuo/" target="_blank">华夏之火</a> 2017-07-15 17:01 <a href="http://www.shnenglu.com/huaxiazhihuo/archive/2017/07/15/215110.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>再论接口http://www.shnenglu.com/huaxiazhihuo/archive/2017/07/15/215105.html华夏之火华夏之火Sat, 15 Jul 2017 03:42:00 GMThttp://www.shnenglu.com/huaxiazhihuo/archive/2017/07/15/215105.htmlhttp://www.shnenglu.com/huaxiazhihuo/comments/215105.htmlhttp://www.shnenglu.com/huaxiazhihuo/archive/2017/07/15/215105.html#Feedback0http://www.shnenglu.com/huaxiazhihuo/comments/commentRss/215105.htmlhttp://www.shnenglu.com/huaxiazhihuo/services/trackbacks/215105.html如果_cȝ设计思\Q是以数据ؓ基础的纵向组l结构,只有唯一的分cL式,有相同基cȝQ就意味着其相似性,共同炚w体现在基cMQ那么,接口是以功能以性质从横向上Q来看待cȝ怼性,q且存在无数的横向视角(否则失L义)?/span>

静态面向对象语aQ这里不考虑templateQ?/span>c++?/span>template是鸭子类型,本质上,c++~译期就是一个功能完备的动态语a。代码上的复用就只能以基cMؓ_度来进行,比如Q函?/span>int fn(Base* bb)Q只?/span>Base的子c,才有资格成ؓ函数fn的会员。函?/span>fn之所以声明其变量bb的类型ؓBaseQ就是ؓ了用类?/span>Base里面的一些东西,一般就是成员函敎ͼ对于清教徒来_不是一般,而是必然Q。假如,函数fn的实CQ就用到Base的几个成员函敎ͼ比如?/span>f1Q?/span>f2Q?/span>…Q?/span>fn。换句话_虽然fn(Base* bb)表面上要求一定要Base的子孙后代才能担当重任,但实际上Q只要别?/span>classQ不必跟Base有半毛钱关系Q只要这?/span>class里面支持f1Q?/span>f2Q?/span>…Q?/span>fnq些操作Q那么原则上他就有资格到fn里面一游。天下唯有d者居之,不必讲究什么贵族。但是,在没有接口的{񔋂严的封建社会里面,q你有惊天之地之能Q就因ؓ你没有某U高늚血l,所以你׃行?/span>

在单根类的王国中Q所有对象都源于ObjectQ也可以通过反射Q通过函数名字q行时获取串f1Q?/span>f2Q?/span>fn{成员函敎ͼ然后再h肉编译器关于参数信息和返回值类型,以摆?/span>Base的类型桎梏,但是Q估计也只有在最Ҏ的时候,才会q样玩。这LQ简直置~译器的cd查于不顾Q静态语a是要尽可能的挖掘编译器cd查的最后一丝潜力?/span>

接口的出玎ͼ在U向的类型关pM撕开一道道口子Q从而尽最大限度释攑֯象的能力。时代不同了Q现在接?/span>IBase里面声明f1Q?/span>f2Q?/span>fn{函敎ͼ然后函数fn的入参ؓIBaseQ也x int  fn(IBase* bb)Q以明确表示fn里面只用?/span>IBase的函敎ͼ语义的要求上更加_և。然后,MclassQ只要其实现了接?/span>IBaseQ就有资Dfn接纳Q不必再?/span>Base之后了。所以说Q要面向接口~程Q就是要面向功能来搬砖,选择的样本空间就qK了很多。接口是比具体类型要灉|Q但不意味着所有的地方必d出现接口Q?/span>classcd没用了Q当然不是,有些地方很有必要用具体cdQ比如说stringcdQ比如说复数q些Q就必须明确规定具体cdQ无ȝ到接口的灉|性。MQ还是那句话Q没有银弹,具体问题具体分析?/span>

使用对象Q其实就是在使用对象的成员函敎ͼ那么Q接口也可以看成是成员函数的_度理工具。所以,接口pCZ一Ҏ员函敎ͼ需要用一Ҏ员函数的时候,用接口最为方ѝ坊间有一些犯virtual恐惧症的c++猿猴Q高高兴兴地用一?/span>function代替接口Q罔օ性能Q时间空_的损失、用上的不便,哎!面向对象是强有力的抽象工P比之于面向过E,函数式,有着独特的优点,反正代码构架上,优先使用面向对象Q绝不会错。而面向对象,必然回避不了接口?/span>

坊间支持面向对象语言中对接口的支持,当以rustQ?/span>scala?/span>trait机制最Zo人喜Ƣ,非R入式啊,自然狗语a的也q好Q但是,本h最反感Q反正,狗语a上一切独有特性,本h都本能地毫无理由排斥。自Ӟjava?/span>C#或?/span>c++的多l承Q最为笨拙,呆板?/span>

java?/span>C#里面Q类能够实现的接口,在类的定义中Q就已经定下来了。类一旦定义完毕,与该cȝ关的接口定下来Q铁板一块,密不透风Q不能增不能减也不能攏V你明明看到一个类已l实C某个接口的所有方法(函数名字和签名一模一PQ但是因ؓ该类没有在定义中明确说明实现该接口,所以编译器死zM承认该类实现q个接口。只能用适配器模式,也即是新造一?/span>classQ实现该接口Q包含旧cȝ对象Q将接口的所有方法都委托l对象的相应函数来做?/span>java的繁文缛节就是这h的,规规矩矩Q毕恭毕敬,一步一个脚印。更ȝ的是Q每ơ传递参数都?/span>new一个适配器对象来满参数的要求,q是最让h隑֏的地斏V?/span>

java?/span>C#的这U接口机Ӟ实在与现实对不上P真是找不CQ何原型,Mcd的物品,q是新造的东西Q我们都不可能一开始就I尽它的所有性质所有功能。就是药物Q都有可能是歪打正着的功能,比如伟哥的功能,是其研发阶段中意想不到的?/span>java?/span>c#的这U接口,会很q扰cȝ完整最化的设计原则,q而加大类的设计难度。当Ӟ它也非一无是处,LQ类支持多少接口Q一眼就看出来了Q毫无疑义。问题是Q接口这U东西,本质上就应该是不定的横向视角来考察cȝ关系?/span>java?/span>C#下的接口问题Q大大限制了接口的用场合?/span>

其次Q承时Q子cdl承了基cȝ所有东西,包括其实现的接口。但是,有些时候,子类q不x有父cȝ某些接口。比如,鸭子应该是鸟类的一个子c,而鸟cL?#8220;会飞”q个接口Q但是鸭子显然不会飞Q也是_虽然鸭子包含了鸟cȝ所有数据,但是它不拥有会飞q个功能。对此,我们希望在编译期_p在要求会飞的场合下,传鸭子对象进LQ编译器报错。但是,ҎQ只能在q行中报错,而且Q还是在调用会飞的成员函数里面才报错。原则上Q编译器是可以知道鸭子不会飞q个概念的,但是Q由?/span>java?/span>C#的接口控制粒度单一Q满不了这U要求?/span>

再次Q接口不能组合,比如_函数fn的参敎ͼ假设名字?/span>ppQ?/span>pp要求同时实现接口IAQ?/span>IB。对此,java?/span>C#中是没有语法满q种多个接口的要求。遇到这U需求时Q只能用强制cd转换Q先随便让参数类型ؓIA或?/span>IBQ然后在必要Ӟ强制转换为另外的cdQ只能在q行时报错。又或者是Q新造一个接?/span>IAB?/span>IAQ?/span>IB上承,然后函数fn的参?/span>pp的类型ؓIABQ但是这P依然存在不Q假如某个类实现IA?/span>IBQ但是没有表明它实现IABQ那么还是不能满_数的要求。接口组合的问题Q不是go?/span>rustQ都没有很好的支持,只能到运行时cd转换才能发生?/span>

最重要的是Q这U接口机制违反了零惩|的机制。就?/span>c++Z来说明,只论接口好了,也即是只有虚函数但是没有成员字段的基cRؓ了方便描qͼq是举例子?/span>

struct IA {virtual void fa() = 0;};
struct IB {virtual void fb() = 0;};
struct Base{…};
struct Derived : public Base, public IA, public IB{…};

接口IA有虚函数Q里面就要有一个指针指向其虚函数表Q所以其内存占用是一个指针的大小Q同理,IB也如此。表面的意思是Derived实现了接?/span>IAQ?/span>IBQ实际上Q在C++中,接口实现是l承Q也是说每?/span>Derived的实例都要包?/span>IAQ?/span>IB里面的数据,指向对应虚函数表的指针字D,也即是有两个指针。这里做不到零惩|的意思,是说Q?/span> DerivedZ表明自己?/span>IA?/span>IB的能力,每个对象付出了两个多余的内存指针I间的代P即便是对象不需要在IA?/span>IB的环境下使用Q这个代价都避免不了。零惩罚抽象Q就是要用到的时候才付出代hQ哪怕这个代价可以大一炏V用不到Ӟ则不必消耗哪怕一点点I间旉上的费。空间上费的问题不在于节省内存Q而在于׃_致的内存布局Q进而媄响到二进制的复用。这一点,非R入式接口׃用也没办法在对象w上包含其所支持的所有接口的虚函数表指针Q因为类型定义完毕,后面q可能在其上d新的接口实现?/span>

而由q几炚w题引甛_来的其他~陷׃必提了。反正,C++Q包?/span>javaQ?/span>C#的这U接口机制最不讨人喜Ƣ了?/span>

至于狗语a的鸭子接口,有时会出现函数名字冲H的问题,E微改一下名字就好了。主要是q种接口机制只要一个类包含了某个接口的所有成员函敎ͼ隐式认为它实现了这个接口。这里会有暗C(误导Q诱惑)Q就是定义类的成员函数时Q会有意或者无意地q就现有接口的成员函敎ͼ同样Q声明接口成员函数时Q也会有意无意地往现有cȝ成员函数上靠。从而导致真正函数的语义上把控不够精准。ƈ且,q种机制太过_暴Q万一q个c虽然支持某个接口的所有函敎ͼ但是q不一定就意味着它就要实现这个接口了。狗语言最令h反感之处是各种自作聪明自以为是的规定。当Ӟ׃狗语a的成员函数可以非侵入式,q个问题造成的不便一定程度上有所减轻Q但是,说实在,p非R入式的成员函敎ͼ本也不太喜Ƣ了。另外,仅仅从语a层面上,不借助文Q很隄道一个类到底实现那些接口Q某个接口被那些cd玎ͼjava?/span>C#的接口在q一点的表现上就很卓。其实,本反感狗语a的最大原因还是因为狗_,相比之下Q?/span>java_?/span>php_等_,可爱多了?/span>

rust?/span>trait形式实提供的接口机制׃多说了,语法形式上简z漂亮,基本上梦寐以求的接口样子是q样子的了?/span>

以上语言的接口,全部属于静态接口,也即是类型所实现的接口在~译期间全部定下来了,q行时就不再有Q何变化。但是,如果对象一直在变化Q好比生物,p人类好了Q有婴儿年青年中年老年Mq些变化阶段Q显然每一阶段的行力都大不一P也拥有不同头衔,不同w䆾。也是_现实中,zȝ生对象的接口集合q一成不变,它完全可以现在就不支持某个接口,高兴时候又可以支持了,不高兴时又不支持了Q聋了就听不到声韻I盲了q不见Q好似消息发送那样子Q显然以上语a是不支持q种动态需求的接口的?/span>

另外Q?/span>com的接口查询虽然发生在q行Ӟ但是Q?/span>com的规范,比如对称性、传递性、时间无x等规则Q硬是把com从动态接口降l到静态接口,q也可以理解Q因为动态接口的应用场景真的q不多。这些都没什么,com最Ҏ的问题,q是在于接口要承载类的功能,当然Q这样也有好处,比如语言的无x?/span>IUnknown的三大成员函数分明就是类的本职工作,AddRefQ?/span>Release理对象的生命周期,Query查询所要的接口。生命周期由对象_度l化为接口粒度,显得太琐碎Q要谨记好几条规则,要小心翼地应付AddRefQ?/span>Release的函数调用,指针也只能减轻部分工作量Q这是_度q小带来的痛苦。?/span>Query的本质就是对象所实现接口集合Q这是对象的本分工作Q现在搞成接口与接口之间的关pR由于接口越俎代庖,承接了类的职责,p求每个接口都要?/span>IUnknownQ本来接口之间就应该没什么关联性的才对Q还Dcom的实C及用,?/span>c++下,非常J复ȝQo人头皮发麅R所以说Q类与接口,一体两面,谁也不能代替谁?/span>

---------------------------------------------------------------------------------------------------------------------------------

备注Q现实世界中Q一U或几种功能p推导出来其他性质Q对应到接口中,是如果对象实现某些接口Q就表示它能实现另外其他接口。目前的语言Q也是接口l承Q子接口l承父接口,那么Q如果一个类实现了子接口Q就表示它也实现了父接口Q语a明面上只支持q种接口的蕴含关pR对于其他的蕴含情况Q只能用适配器来凑数Q而在非R入式接口中,其语a形式显得更加的累赘Q这一点,?/span>java上尤为突出。其实,说到底,适配器模式只是I补语a不支持接口蕴含机制的产物?/span>




华夏之火 2017-07-15 11:42 发表评论
]]>
c++面向对象的类设计http://www.shnenglu.com/huaxiazhihuo/archive/2017/07/14/215101.html华夏之火华夏之火Fri, 14 Jul 2017 03:48:00 GMThttp://www.shnenglu.com/huaxiazhihuo/archive/2017/07/14/215101.htmlhttp://www.shnenglu.com/huaxiazhihuo/comments/215101.htmlhttp://www.shnenglu.com/huaxiazhihuo/archive/2017/07/14/215101.html#Feedback0http://www.shnenglu.com/huaxiazhihuo/comments/commentRss/215101.htmlhttp://www.shnenglu.com/huaxiazhihuo/services/trackbacks/215101.htmlcȝ设计在于用恰到好处的信息来完整表达一个职责清晰的概念Q恰到好处的意思是不多也不,了Q就概念׃完整Q多了,显得冗余,累赘Q当然特例下Q允许少许的重复Q但是,q里必须要有很好的理由。冗余往往意味着包含了过多的信息Q概늚表达不够_ևQ好?/span>gotoQ指针,多承这些货Ԍ是因ؓ其过多的内涵Q才要严格限制其使用。好像,more effective c++上说的,class的成员函敎ͼ应该是在完整的情况下保持最化。但是,q里我们的出发点Q是成员数据的完整最化?/span>

最化的好处是可以保持概念最大的独立性,也意味着Q可以用最的代h来实现这个概念,也意味着对应用层的代码要求越,非R入式Q好?/span>c++11 noexcept取代throw()Q好比从多承中分化出来接口的概念,好比不考虑多承虚l承的普通成员函数指针。又比如Q如果不要求只读字符串以0l束Q那么就可以把只dW串的Q何一部分都当成是只读字符丌Ӏ类的对外功能固焉要,但是Q类不能做的事情Q也很重要?/span>

首先是要有清晰的概念以及q个概念要支持的最基本q算Q然后在此基上组l数据,务求成员数据的最化。当Ӟ概念的生,q拍着脑袋惛_来的Q是因ؓ代码里面出现太多那种相关数据的次敎ͼ所以就有必要把q些数据打包hQ抽象成一个概c好比说Q看?/span>stl法函数参数到处开始结束的q代器,有必要把开始结束放在一赗比如说Q?/span>string_view的出玎ͼq里假设其字W存储类型ؓcharQ?/span>string_view是q箋char内存块的意思,可以q样表示

struct string_view

{

         const char* textBegin;

         size_t length; //或?/span> const char* textEnd

};

q里的重ҎQ?/span>string_view里面的两个成员字D늼一不可Q但是也不必再添加别的什么其他东ѝ然后,在这两个数据上展开实现一pd的成员函敎ͼq里Q成员函数和成员字段q两者,有一点点鸡生蛋生鸡的U结Q因为必要成员函数的集合Q原始概늚l化Q,成员函数军_了成员字D늚表示Q而成员字D定下来之后Q这反过来又能够验证成员函数的必要性。不怎么说都好,成员函数的设计,也必遵从最完整化的原则。再具体一点,是说但凡一个成员函数可以通过其他成员函数来实玎ͼ意味着q个函数应该赶出cdQ作为全局函数存在。当Ӟq也不是L的教条,有些很特D的函数Q也可以是成员函敎ͼ因ؓ成员函数的用,实很方ѝ?/span>

可能会有疑惑Q感觉所有的成员函数其实都可以是全局函数。或者说Q我们可以对每一个成员字D都搞一?/span>set?/span>get的函敎ͼ那么所有的其他成员函数可以是全局函数的Ş式,很容易就可以遵守最完整化的原则。当Ӟq是明显hQ拒l思考的恶劣行ؓ。与其这Pq不如就开放所有的成员字段Q那样子p?/span>c语言的套路了。所以的法论是,一个函敎ͼq里假设是全局函数Q如果它的实现必要讉K到成员字D,不能通过调用该类的成员函敎ͼ一般不?/span>getQ?/span>setQ来辑ֈ目的Q或者,也可以强行用其他函数来完成Q务,但是很麻烦,或者要付出旉I间上的代hQ那么就意味着q个函数应该是该cȝ成员函数?/span>

cȝ设计Q就是必不可的成员字段和必不可的成员函数Q它们一P实现了对cȝ原始概念的完整表达,其他什么的Q都不必理会。一个类如果不好写,往往意味着q个cȝ功能不专一Q或者其概念不完_q时Q可以不要急着抽象Q如果一个类有必要诞生,那么在代码的~写中,该类的抽象概念将一再重复出玎ͼ猿猴对它的理解也来清晎ͼ从而,水到渠成地把它造出来。所有非需求推动,非代码推动的Q拍着脑袋Q想当然的造类行ؓQ都是在臆造抽象,q实际生活的艺术,最l将被淘汰?/span>

cȝ设计Q其着眼点在于用必要的数据来完整表达一个清晰的概念。而承,则是对类的概念进行细化,也就是分c,好比说生物下面开出来动物、植物这两个子类Q就是把生物分成动物、植物这两类Q承与日常生活的分cM太一Pl承的分cL式是开攑ּQ根据需要,随时可以d新的子类别。整个类的体p,是一颗严格的单根树,Mcd能有一个根cR从Mcd始,只能有一条\径回溯到最开始的根类Q?/span>java?/span>C#中就?/span>ObjectQ所有的c都z?/span>ObjectQ这是一大树。单根系下,万物皆是对象Q这自然很方便,LQ这׃语言层面上直接支?/span>c++ std的垃?/span>any了。而由?/span>java?/span>C#完善的反信息,抛弃静态类型信息,也可以做动态语a层面上的事情Q?/span>cQ?/span>c++?/span>void*Q所有的动态类型信息全部都在猿猴的大脑中?/span>javaq_上生存着大把的动态语aQ而且Q性能都还很不错?/span>

相对很多语言来说Q?/span>c++是怪胎是异数Q自有其自n的设计哲学,它是多根pȝQ它不可能也没必要搞成单根系Q当Ӟ我们可以假设一个空c,然后所有的c都默认l承自这个空cR?/span>c++的所有类l成一个森林,林里的树都长自大地。但是不怎么说都好,只能允许单承,千万不要有多l承Q这是底U,千万千万不能q背Q当Ӟ奇技淫y的场合,׃必遵守这个戒条,多承千般不是,但是不可或缺Q因为它可以玩出来很多花Pq且都很实用很必要)。最LQ单根系出来的内存布局直观可预,一定程度上跨编译器Q只有良好的内存布局Q才有望良好的二q制复用。另外,父类对子cM无所知,不要引用到子cM丁点的信息,要保持这U信息的单向动性?/span>

在这U单根系的等U分明的阶体系下,一切死气沉沉,没有一点点的社会活力。显Ӟ只有同属于同一父类的类别之_才能׃n那么一丁点可怜的共性。如果没有接口捣乱,是怎样的悲剧,最好的例子Q?/span>mfcQ真是厉宻I没有用到接口Q居然可以做出来严}满大多数需要的gui框架Q没有接口,q不表示它不需要,因ؓmfc开了后门,用上了更厉害的玩?/span>----消息发送,即便如此Q?/span>mfc有些地方的基c还有依赖到子类Q这很让h无语了?/span>

c++下,cȝ设计l对不对儿戏Q一定要清楚自己惌的是什么,抽象出来的概忉|不会变成垃圾。大而全的类Q远q不如几个小而专的细cR?/span>javaQ?/span>C#下的cd发很方便Q但是粒度过大,把一揽子的东襉K丢给你,强卖ZQ反正只要类一定义Q必然相应的׃出现一大坨完善的反信息,而对象里面也包含了一些无关紧要的成员字段Q而对象的讉KQ也全部都是间接引用的访问,虽然Q现在计机性能q剩Q这些都无伤大雅?/span>c++l了开发者最大的选择Q而搞c++的猿_基本上都智力q剩Q对于每U选择Q都清楚其背后的代h以及所要到辄目的Q所以虽然开发时候,存在心智包袱影响开发效率,但是Q但内心׃会存在什么性能包袱的负|感。就个h而言Q还是喜?/span>c++q种最高自由度的语aQ有时候,对于内存最l致的控Ӟ可以得到更精的设计,q里无关q行性能Q好比说Q在c++中,只要内存布局一_即便是不同类型的对象Q通过强制cd转换来统一对待Q进而做匪夷所思之事,好比COM里面Qؓ了聚合复用,一个类Q竟然可以针对同一个接口提供两套实现方式。这U方便,在其他强cd语言中是不支持的?/span>

某种意义上讲Q?/span>c++在面向对象上提供的语a机制Q就是ؓ了方便地生成各种内存布局Q以及此内存布局上所能支持的操作Q虚函数用以生成一堆成员函数指针,l承则用以方便地生成一坨成员字D,……。所以,c++的面向对象就是面向内存布局地设计,而多l承、虚l承、模板这些鬼东西很容易就D内存布局的失控,不过Q如果用得当,却又有鬼斧神工之奇效Q创造出来其他语a所没有的奇qV真的,论动态行术,M语言?/span>c++q个大h面前都是q儿园里的小学生?/span>

Z引出接口Q本座花大力气做U普。这也没办法Q因为类虽然是基Q但是静态面向对象的_֍Q全部都在接口上。只有清晰明类的功能职责,才能理解接口的必要性以及其多样性。那么,可不可以只有接口Q没有类的。可以,好像com那样子,而代hQ用v来,各种不方ѝ这个世界,从来׃存在包治癄之万能药。什么事情都能做的意思就是什么都做不好?/span>



华夏之火 2017-07-14 11:48 发表评论
]]>
c++的面向对象之前传http://www.shnenglu.com/huaxiazhihuo/archive/2017/07/12/215093.html华夏之火华夏之火Wed, 12 Jul 2017 10:17:00 GMThttp://www.shnenglu.com/huaxiazhihuo/archive/2017/07/12/215093.htmlhttp://www.shnenglu.com/huaxiazhihuo/comments/215093.htmlhttp://www.shnenglu.com/huaxiazhihuo/archive/2017/07/12/215093.html#Feedback1http://www.shnenglu.com/huaxiazhihuo/comments/commentRss/215093.htmlhttp://www.shnenglu.com/huaxiazhihuo/services/trackbacks/215093.html此文只是杂ؕ的记录一点点对于面向对象的个人看法,有些观点也ƈ非原创。没什么系l性可aQ虽然笔者稍作整理,但始l还是显得很散ؕQ只是一些片D늚堆积?/span>

׃涉及的题目过于庞大,反而不知道如何下笔。先|列一下问题,之间没有严格的先后之分,Ua是W者想到哪里,写到哪里。也不一定就会解{。承的本质是什么?Z么一定要有接口?c++多承ؓ何饱受非议,真的׃无是处?ZW者就反感go接口Q反?/span>go独有的一切,W者都是下意识的排斥?功能J杂?/span>ComQ结?/span>C++的自w特点,能否改头换面Q?/span> ……

在原教旨眼里Q面向对象的教义是对象+消息发?/span>”Q整个程序由对象l成Q而对象之间的׃仅只通过发送消息响应消息来交互Q程序的功能都是在对象与对象的来回消息发送中完成Q用现实事情cLQhcd是一个个zȝ生的对象Qhc通过消息的往来,比如语音、文字、广播等Q有人制造新闻,有h接受到这些消息后Q各自反应,最后完成一切社会活动。好像说得有Ҏ象,展开来说Q其实就是,消息的发送者,原则上不需要事先了解目标对象的M背景资料Q甚至他明知道对方不鸟消息,比如_明明Ҏ是一个乞丐,但是q不妨碍你向他?/span>500万h民币Q反正,消息是q样发送出ȝ。然后,对象接受到消息之后,各自反应,比如说有人真的借钱l你Q有人哭IP有h嘀咕你到处借钱Q无耻;……Q各式各P不一而?/span>

听v来好像hcȝ会活动就是消息的往来下推动Q艰隄前进Q但是,q能拿来搬砖吗?可以的,真的可以Q即便是C语言Q都可以来搞消息发送这U高大上的事情,好?/span>win32那样子,通过SendMessage函数l窗口发送消息,其签名如下:

LRESULT SendMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);

好像参数有点多。说白了Q消息发送就相当于成员函数函数调用的一个新马甲Q换了一U说法而已。成员函数调用,形式是这样子Q?/span>obj.fn(param1, param2, …)Q涉及到对象Q函数名字,q有参数Q可能参数数量不止一个,参数cd也各不一Pq些都没关系?/span>hWnd为窗口,也即是对象;Msg为函数名Uͼ现在用正整型~号来代表,有些消息发送系l用原子Q?/span>qt好像是用字符Ԍ性能堪忧啊)Q?/span>wParamQ?/span>lParam可以看成void*cdQ也x函数的参敎ͼ用这两个值封装所有的参数。天真,天下函数参数cd成千上万Q参数数目或0个、或1个、或三五个、或七八个,?/span>wParamQ?/span>lParamq两个弱鸡,p装得过来?可以的,通过强制cd转换Q就可以?/span>void*的g?/span>char?/span>int?/span>float{|又或者是参数打包ؓl构体,q样子,可以应付千千万万的函数参数要求Q这样子Q不要说Q有两个wParamQ?/span>lParam来传递参敎ͼq是只有一个,也都可以应付千千万万的函数要求?/span>

那么Q如何响应消息?可以参?/span>win32的原?/span>api开发,q里׃展开了。原理就是,每个对象都有一个函数指针,那个函数把全部的成员函数都压~在一个庞大的switch语句里面Q每个消息编?/span>case分支Q就代表一个成员函敎ͼ昄Q这个分支,要先?/span>wParamQ?/span>lParam里面在还原成对应参数的实际情况,然后再执行相应操作?/span>

SendMessage昄抹去了所有窗口的具体cd信息Q甭你是按钮、漂亮按钮、菜单、编辑框?/span>……Q全部一律都退化成H口对象。要往~辑框里面添加文字,q它发送添加文字的消息Q?/span>wParamQ?/span>lParam带着要添加的文本和长度。而不是调用编辑框的添加文字的成员函数来做q个事情Q最明显的事情,是也可以给按钮H口也发送添加文本的消息Q虽然按钮窗口对此消息的反应是啥也不做。o人惊讶的是,你可以子cd一个按钮窗口,让它Ҏ加文本的消息做出反应Q这完全是可以的?/span>

昄Q原教旨的面向对象教义,的而且,灉|Q解耦彻底,不同cd对象之间的耦合关系一律不复存在,之间只有消息的往来。随心所Ʋ的发送消息(胡ؕ调用成员函数Q,自由自在的反应消息(一切全无契U可aQ,不理睬,或者这一M理睬下一d动了Q或者这一d了下一d拒绝反应。甚臻I消息q可以保存,排队Q求反,叠加什么的Q也x消息已经是一U抽象数据类型了Q支持多U运。相比于不知所谓的Zcȝ静态面向对象(l承装多态)Q简直不可同日而语Q太多的U束Q呆板的语法Q深入的哲学思考,架床叠屋的类型关p,也好意思学人家叫面向对象?/span>

当然Q对?/span>+消息发送这U机Ӟ付出的代价也是很巨大的,基本上,函数调用的静态类型检查不服存在,所有问题都要到q行时才能发现。ƈ且,消息发送的语法也很不直观,必须各种cd转换Q而响应消息时又必{换回厅R此外,为函数定义消息编P也很恶心。不q,q些在动态语a里面都不是问题,反正Q动态语a里面没有静态类型约束。另外,W者用template、全局变量、宏{奇技淫yQ在c++里面Q已l实Ccd安全的消息发送框Ӟ比如Q?/span>Send(obj, kAppendText, U8String(“hello”))Q而对象实现对消息的响应,直接也是成员函数的Ş式,q且q是非R入式的,也即是说Q在main函数之前Q可以随时在L地方l对象添加新的消息反,所有参Ccd转换以及q回g的类型{换,全部都不需要了?/span> 但即便是q样Q也不赞成原教旨的面向对象到处泛滥。原因是Q用它写出来的程序,cd层次很不清晰Q相比于架构良好的类形式的面向对象程序,可读性远q不如,也不好维护。更深刻的原因是Q对?/span>+消息发送的威力太惊人,用途太q,M多态上的行为,都可以用它来做。什么都可以做,意味着什么都量不要让他来做?/span>

其实Q即?/span>java?/span>C#q种l承装多态的面向对象千般弱鸡各种J文~节Q也不妨h家称霸天下,到处行。你对象+消息发送再妙Q流行度都不及h?/span>java一个零_obj cq不是靠着ios的流行才有所赯Q挤入排行榜十名内。虽然说市场不能说明什么,但是Ҏ如此悬殊Q自有其道理?/span>

再说Q静态类型的成员函数调用模式Q广泛存在于人类C会zd中。h与h之间的很多事情,其实只要满一定的条gQ必然就会发生,其后果也可以预料。很多消息的发送,其实是有考虑到对方的w䆾问题Q才会发P好比孩子跟爸妈要零用钱的消息,孩子再发送要零用q消息Q一定是针对亲h才发L。真相是Q往往要满一些必要条Ӟ消息才得以发P当然Q只要你高兴Q随旉可以发vM消息Q问题是Q这Uh多半不正常。量体裁,针对什么样的问题,应该采用相应的手段Q一招鲜吃遍全天下,行不通的。具体问题,必须具体分析。每U问题,都有自己最独特有效的解法。笔者在原教旨的面向对象上重复太多内容,q自己都恶心Q以后应该很再提及?/span>

所以说Q面向对象的设计Q首先应该采用的必然q是l承装多态的思\。在此基上,Ҏ不同的动态要求,采用不同{略来应寏V企囄万能的消息发送来代替静态类型面向对象的荒谬如同用僵化的面向对象来模拟一切动态行为,两者都是犯了同L毛病。可是,静态面向对象做设计Q又实困难重重Q而最l的开发成果,L让h难以满意。那是因为,q大力_众寚w态面向对象一些基本概늚理解Q存在这样那L误区Q而由于面向对象语aQ?/span>javaQ?/span>C#Q还~Z一些必要机ӞD设计上出现妥协,原则性的错误积深Q以至于最后崩盘。其实,不要说一般hQ就q大人物Q在面向对象上,也都只是探烦Q好?/span>c++之父BSQ搞出来多承,虚承,iostream体系Q在错误的道路上Q越走越q,走远?/span>

好吧Q其实,多承,q是很有作用的,在很多奇技淫y上很有用武之圎ͼ很方ѝ但是,用多l承做架构的危险Q就在于其功能太q强大。这意味着它要沦落成ؓgoto啊、指针啊那样的角Ԍ先甭它ȝ尬。多l承的最重要角色Q概念实玎ͼ也即是接口,也即是定义一批虚函数Q里面没有Q何数据,q个抽象必鲜明,q一点,java?/span>C#做得很C。就应该从多l承上提炼出来这么一个好东西Q咦Q对了,Z要有接口Q没有接口,q的不行吗Q是的,静态面向对象里面,接口实必不可少?/span>

l承Q本质上是分类学。而分c,最重要一点,是M一件元素,必须也只能只属于其中一个类Q不得含p。可以存在多U分cL式,但是Q一旦确定某U分cL式,那么集合里面的一个东西,必d能属于其中一大类。承,是分类的一再细化,也是概念的l丰富。比如说Q从生物到动物到Z^动物Q概念包含的数据来多。所以说Q承体现的是数据上的丰富关p,它强调的是数据的U篏Q从q古基类开始,一路积累下来的数据Q全部必不可,也不得重复,一旦违反这条底U,意味着l承体系上的错ؕ。承,相当于类型的gQ缺乏硬件元器gӞ无法完整表达该cd的概c比如说Qhcd分ؓ男h、女人,自然Q男人有男h的阳刚,女h有女人的阴柔Q那么阴阛_体怎么办,集两性之所长,Np阴阳人多l承与男人女人吗Q那么,q样l承下来Q阴阳h岂不是就是有两个_四只手,四条腿了Q啊Q这不是阴阳人,q是hQ抑或是怪物。所以,阴阳人应该是人里面的一个分支,也即是,人的分类Q就要有男h、女人、阴阳hq三大基cR再ơ强调,l承是ؓ了承数据,而不是ؓ了功能,功能只不q是数据的附带品。那么,怎么描述男h的阳刚、女人的阴柔Q怎么避免阴阳人引入后Q分别从男h阛_Q女人阴柔上复制代码呢?此外Q再ơ考虑q四边形,下面好像又有菱ŞQ有矩Ş两大c,然后w集菱Ş矩Ş的正方ŞQ这里的分类该如何处理,N忍不住要让正方Ş多承菱形矩形吗Q从q个意义上讲Q在同一体系下,多承的出现Q理所当然Q大错特错,由此可知Q?/span>iostream是败类?/span>iostream通过虚扉K免绝世钻石的出现Q但是这个虚l承啊,真是要让人呵cC++中引入虚l承真是Q怎么说呢Q好吧,也算脑洞大开的优良物品,也不是完全一无是处,LQ在iostream上就大派用场了。你p_虚扉K点不好了Q就一点,Z子子cȝ千秋ZQ子cd虚l承基类Q子cd子子cd响,p一点,你能忍?/p>

 

H然发现Q文章已l很长了Q不了Q这打住。至于非侵入式接口,以后再说吧!



华夏之火 2017-07-12 18:17 发表评论
]]>
再议c++的面向对象能力之?/title><link>http://www.shnenglu.com/huaxiazhihuo/archive/2017/07/11/215082.html</link><dc:creator>华夏之火</dc:creator><author>华夏之火</author><pubDate>Tue, 11 Jul 2017 03:56:00 GMT</pubDate><guid>http://www.shnenglu.com/huaxiazhihuo/archive/2017/07/11/215082.html</guid><wfw:comment>http://www.shnenglu.com/huaxiazhihuo/comments/215082.html</wfw:comment><comments>http://www.shnenglu.com/huaxiazhihuo/archive/2017/07/11/215082.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.shnenglu.com/huaxiazhihuo/comments/commentRss/215082.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/huaxiazhihuo/services/trackbacks/215082.html</trackback:ping><description><![CDATA[<p style="text-indent:21.0pt">C++<span style="font-family:宋体;">的面向对象设计能力,?/span>java<span style="font-family:宋体;">Q?/span>C#<span style="font-family:宋体;">q两个杂相比,一直都是一个大W话Q现在谁敢正儿八l地?/span>c++<span style="font-family:宋体;">搞面向对象的框架pȝQ业界都?/span>java<span style="font-family:宋体;">?/span>C#<span style="font-family:宋体;">搞设计模式,那关</span>C++<span style="font-family:宋体;">什么事情了。?/span>C++<span style="font-family:宋体;">也很有自知之明,很知,</span>98<span style="font-family:宋体;">q之后,׃怎么对外宣称自己是面向对象的语言Q就不怎么搞面向对象研I了Q难道是</span>c++<span style="font-family:宋体;">下的面向对象已经被研I彻Q)Q一直在?/span>template<span style="font-family:宋体;">的老本Q一直到现在Q?/span>template<span style="font-family:宋体;">q笔丰厚的遗产,貌似q够</span>c++<span style="font-family:宋体;">吃上几十q。今时今日,</span>virtual<span style="font-family:宋体;">早就沦落?/span>template<span style="font-family:宋体;">的附庸,除了帮助</span>template<span style="font-family:宋体;">搞点cd擦除的行术之外,很隑ֆ见到其n׃。有那么几年Q业界反?/span>c++<span style="font-family:宋体;">的面向对象范式,Ҏ</span>virtual<span style="font-family:宋体;">Q特别是</span>function<span style="font-family:宋体;">出现之后Q要搞动态行为,更加不?/span>virtual<span style="font-family:宋体;">的什么事情了。而那几年Q本座也学着大神忌讳</span>virtual<span style="font-family:宋体;">关键字。现在大家似乎已l达成共识,</span>c++<span style="font-family:宋体;">里头的面向对象能力很不完善,要玩面向对象应该找其他语言Q比?/span>java<span style="font-family:宋体;">?/span>C#<span style="font-family:宋体;">杂碎Q或者更动态类型的语言Q好?/span>python<span style="font-family:宋体;">Q?/span>Ruby<span style="font-family:宋体;">Q或者干脆就是原教旨的面向对象(消息发送)Q?/span>object C<span style="font-family:宋体;">Q?/span>smalltalk<span style="font-family:宋体;">?/span></p> <p style="text-indent:21.0pt"><span style="font-family:宋体;">是啊Q?/span>1<span style="font-family:宋体;">、没有垃圑֛Ӟ</span>2<span style="font-family:宋体;">、没有原生支持的完善反射能力Q?/span>3<span style="font-family:宋体;">、多l承、虚l承D的复杂内存布局。这三大山面前Q?/span>c++<span style="font-family:宋体;">的码猿哪敢染指什么面向对象,只在q不得已的情况下Q小心翼地使用</span>virtual<span style="font-family:宋体;">。但是,事实上,要玩面向对象Q?/span>c++<span style="font-family:宋体;">原来也可以玩得很炫,甚至Q可以说Q关于面向对象的能力Q?/span>c++<span style="font-family:宋体;">是最强的Q没有之一Q。这怎么可能Q?/span></p> <p style="text-indent:21.0pt"><span style="font-family:宋体;">所谓的面向对象Q说白了Q就是对动态行为的信息支持Q能在面向对象设计上独领风骚的语aQ都是有着完善的运行时cd信息Q就q?/span>lisp<span style="font-family:宋体;">Q其q行时元数据也都很完备。静态强cd语言Q?/span>java<span style="font-family:宋体;">?/span>C#<span style="font-family:宋体;">Q与动态语a比,昄有着强大的静态类型能力(q不是废话吗Q,能在~译期就提前发现cd上的诸多错误Q但是也因此带上静态约束,D呆板、繁琐的代码Q?/span>java<span style="font-family:宋体;">的繁文缛节,是最好证明;而动态语a恰好相反Q代码简z,废话,但是丧失静态信息,所谓重构火葬场Q那都是血和泪的教训。静态语a与动态语a真是一对冤Ӟ如同光的波粒性,׃所长恰是彼之所短,׃所短又是彼之所长,g熊掌不可兼得。?/span>C++<span style="font-family:宋体;">竟然能集两家之所长,在静态语a的领域中玩各U动态行术,比如动态修改类型的反射信息Q千奇百怪的花样作死Q心病狂的cd转换Q;在动态范畴里面,又可以在~译期榨取出来静态类型信息,比如Q消息发送的参数信息Q想想win32的无cd的wparam和lparamQ每ơ都要猿猴对照手册解码,从而最大限度地挖掘~译器的最大潜力。所以说Q?/span>c++<span style="font-family:宋体;">是最强大的面向对象语aQ没有之一。而把静态和动态融Z体之后,</span>c++<span style="font-family:宋体;">的抽象能力也到达一个全新的高度Q自动代码生成,以后再发挥,q是一个庞大的N?/span>C++<span style="font-family:宋体;">令h发指的强大,l对q远乎{闲猿猴的想象,特别是那?/span>c with class<span style="font-family:宋体;">的草覆虫原始生物?/span>C++<span style="font-family:宋体;">只在部分函数领域的概念上表现令h不满Q比?/span>lambda<span style="font-family:宋体;">表达式的参数cd自动推导Q?/span>monad<span style="font-family:宋体;">表达式,~Z原生的gq求值等。当Ӟ</span>c++<span style="font-family:宋体;">整个的设计理念非常繁杂随心所Ԍ但是Q却可以在这一块؜沌里面整理出来一些D世无双的思想体系Q就是说Q?/span>c++<span style="font-family:宋体;">是一大堆原材料,q有很多厨房用具Q包括柴火,让猿猴自行下厨,做出来的菜肴可以很难吃,也可以是满汉全席Q全看猿猴的手艺?/span></p> <p style="text-indent:21.0pt"><span style="font-family:宋体;">当然Q要?/span>c++<span style="font-family:宋体;">里头搞面向对象,多承,虚承的那一套,必须d抛弃。最大的问题是,多承会D混ؕ未知的二q制内存布局Q虚函数表也一塌糊涂,十几q前Q?/span>c++<span style="font-family:宋体;">设计新思维的基?/span>policy<span style="font-family:宋体;">的范式,虽然令h耳目一斎ͼ也因U范式下对象的内存布局千奇百怪,所以,即便是最d的流行也没有出现q。当Ӟ也不可能大规模搞消息发送这U很</span>geek<span style="font-family:宋体;">的套路,功能太泛化了Q其实,消息发送就是动态的l对象添加成员函敎ͼq且可以在运行时知道对象有多成员函敎ͼ那个成员函数可以对该消息做出反应Q消息可以是字符Ԍ整型</span>ID<span style="font-family:宋体;">Q原子)Q?/span> MFC<span style="font-family:宋体;">的消息映表</span>(BEGIN_MESSAGE_MAP<span style="font-family:宋体;">Q?/span>…)<span style="font-family:宋体;">是一个功能严重羃水版的好例子Q?/span>c++<span style="font-family:宋体;">下支持消息映的库,l对可以比破</span>mfc<span style="font-family:宋体;">的那一套要好上千百倍,不管是性能、类型安全、用方便上。目前除了在</span>gui<span style="font-family:宋体;">q种变态的场合下才需要大搞消息发送,其他场景Q完全可以说用不上,虽然说消息发送很强大很灵z,但也因ؓ其杀伤力太厉宻I反而要更加慎重。这好比</span>goto<span style="font-family:宋体;">Q好比指针,好比</span>stl<span style="font-family:宋体;">的P代器Q什么都能做的意思,是什么都量不让它做?/span></p> <p style="text-indent:21.0pt"><span style="font-family:宋体;">那么Q?/span>c++<span style="font-family:宋体;">下搞面向对象Q还有什么法宝可用呢Q当Ӟ在此之前Q我们先要直面内存分配。内存既?/span>c++<span style="font-family:宋体;">的安w立命之本,又是</span>c++<span style="font-family:宋体;">沦落水狗丧家犬之q后大黑手。假如不能ؓ所Ʋؓ的操作内存,那么</span>c++<span style="font-family:宋体;">的折腾法子,奇技淫yQv码要L一大半以上。而由于要支持各种花样作死的内存操作,</span>c++<span style="font-family:宋体;">的垃圑֛收迟q未曑և玎ͼp以巨之大能整出来的</span>.net<span style="font-family:宋体;">那么好的</span>gc<span style="font-family:宋体;">Q霸王硬上弓Q在l原?/span>c++<span style="font-family:宋体;">强硬加上托管功能Q垃圑֛ӞQ都出力不讨好。可见未来垃圑֛Ӟ?/span>c++<span style="font-family:宋体;">来说Q嗯Q想惛_好了。内存是资源Q没错,?/span>raii<span style="font-family:宋体;">来管理,也无可厚非。但是,内存却是一U很Ҏ的资源,</span>1<span style="font-family:宋体;">、内存时对象的安w立命之所Q?/span>2<span style="font-family:宋体;">、不同于普通资源,内存很多Q不需要马上用完就急急忙忙启动清理工作,只要pȝq有大把IZ的内存,qq有很多被浪费了的内存,都不要紧Q?/span>gc<span style="font-family:宋体;">也是因ؓq个原因才得以存在。相比内存,普通资源给人的感觉是数量及其有限Q然后要提交工作l果Q否则之前所做努力就废了。所以,对于内存Q应该也要特别对待。就?/span>raii<span style="font-family:宋体;">Q也要采用专门的</span>raii <span style="font-family:宋体;">?/span></p> <p style="text-indent:21.0pt"><span style="font-family:宋体;">假设我们的程序里面用多U内存分配器Q比如说Q每个线E都有自׃有的内存</span>allocator<span style="font-family:宋体;">对象Q然后,U程之间的共享数据由全局的内存分配器分配Q线E的内部对象都用U程的专?/span>allocator<span style="font-family:宋体;">来分配,那么Q内存分配器是一个线E局部变量(</span>tls<span style="font-family:宋体;">Q?/span>thread local storage<span style="font-family:宋体;">Q。于是,可以规定Q所有的内存分配都通过</span>GetTlsAllocator()<span style="font-family:宋体;">?/span>new<span style="font-family:宋体;">对象Q当Ӟ定是全局׃n变量的话Q没办法Q就只能?/span>GetGlobalAllocator()<span style="font-family:宋体;">?/span>new<span style="font-family:宋体;">对象。那么,有理q信,启动一个Q务时Q我们先定义一?/span>arena allocator<span style="font-family:宋体;">变量Qƈ令其成ؓ当前U程的专属内存分配器Q那么这个Q务后面的所?/span>new <span style="font-family:宋体;">出来的对象,包括循环引用Q都不必兛_。只要Q务一l束Q这?/span>arena allocator<span style="font-family:宋体;">变量一释放Q所有寄生在它n上的对象Q全部也都消失得q干净净Q没有Q何一点点的内存泄霌Ӏ就Q务内部有大量的内存泄Ԍ那又如何QQ务一l束Q所有跟此Q务有关的一切内存,全部成块清空。MQ不要以常规</span>raii<span style="font-family:宋体;">来解军_存困境,解放思想Q在内存释放上,我们可以有九U办法让它死Q而不是仅仅靠</span>shared_ptr<span style="font-family:宋体;">Q?/span>unique_ptr<span style="font-family:宋体;">Q?/span>weak_ptr<span style="font-family:宋体;">q些狭隘的思维?/span></p> <p style="text-indent:21.0pt"><span style="font-family:宋体;">其次Q完善的面向对象设计Q避免不了完备的反射Q用以在q行时提供动态类型信息,无参模板函数可以把静态类型映成全局唯一变量Q好比,</span>TypeOf<vector<int>><span style="font-family:宋体;">Q返?/span>vector<int><span style="font-family:宋体;">的全局唯一?/span><span>const TypeInfo*</span><span style="font-family:宋体;">对象Q这个对象包含了</span>vector<int><span style="font-family:宋体;">的所有静态类型信息,可以q么_在静态类型层面上</span>vector<int><span style="font-family:宋体;">所能做的Q何事情,比如定义一?/span>vector<int><span style="font-family:宋体;">的变量,也即是创建对象;遍历、添加元素、析构、复制赋倹{元素数量等{一切操作,?/span>vector<int><span style="font-family:宋体;">对应?/span>TypeInfo<span style="font-family:宋体;">对象Q统l都可以做到。所不同的是Q?/span>vector<int><span style="font-family:宋体;">的静态类型代码,只能用于</span>vector<int><span style="font-family:宋体;">自n的情况(q样子可攑֜源文件中Q,又或者是通过</span>template<span style="font-family:宋体;">Q表现行为类g</span>vector<int><span style="font-family:宋体;">的数据类型(代码必须在头文g上)。而用</span>TypeInfo*<span style="font-family:宋体;">做的事情Q全部都在运行时发生Q所有的静态类型信息,全部被带到运行时来做Q所以这些代码全部都可以处在源文仉面,甚至动态库里头Q只不过?/span>TypeInfo*<span style="font-family:宋体;">操作的对象是一个二q制内存布局?/span>vector<int><span style="font-family:宋体;">一模一L内存块,可以通过强制cd转换Q把q行时的内存块{换成静态编译时?/span>vector<int><span style="font-family:宋体;">。其实这里的思想Q就是想方设法将丰富多彩的静态类型信息无损的保存到运行时中,让编译时能做的事情,q行时也可以做。差别在于,一个是用静态类型信息来做事情,q里QQ何一点点cd上的错误Q都会让~译器很不高_一个则是用动态类型信息来做事情,q里Q显然只能让猿猴~译器。这里,可见动态类型信息和静态类型信息的表达能力是等LQ也x同等重要性的意义Q而静态类型信息的意义有多大,怿大家都知道?/span></p> <p style="text-indent:21.0pt"><span style="font-family:宋体;">那么Q如何徏立完备的反射信息Q这个必d能用宏来配合完成Q外部工L成的反射信息代码Q功能很不完备,另外Q?/span>c#<span style="font-family:宋体;">?/span>java<span style="font-family:宋体;">{的反射信息全部都是~译器生成的Q可定制性很差。我们需要的是一炚w不逊色于静态行为的动态行为。所以,只有pp行管理反,才能做到真正意义上的完备反射。必要时Q我们还可以在运行时修改反射信息Q从而动态地增删对象的行为方式,改变对象的面貌。看到这里,是否觉得很多的设计模式,在这里会有更清晰更简z的表达方式呢,甚至Q轻而易丑ְ可以出现新的设计模式。比如,以下定义对象反射信息的代码?/span></p> <p style="text-indent:21.0pt"><span style="font-family:宋体;">?/span>c++<span style="font-family:宋体;">下,׃全局变量生命周期的随意性(构造函数调用顺序不定Q析构顺序也不确定)Q大安很忌讛_使用Q虽然全局变量功能很强大,很多时候都避免不了。但是,标准上还是规定了全局变量的顺序,所有的全局变量必须?/span>main<span style="font-family:宋体;">函数之前构造完成,其析构函C只能?/span>main<span style="font-family:宋体;">函数l束后才调用。另外,函数的静态变量必d其第一ơ访问之前构造完整。基于这两点Q我们就可以?/span>main<span style="font-family:宋体;">函数之前构徏全部的反信息,程是这样子Q所有的cd的反对象都是以函数内部的静态指针变量存在,他们都通过调用</span>GetStaticAllocator()<span style="font-family:宋体;">的内存分配器来创建,q样子,提供反射信息的函敎ͼ避免了其内?/span>TypeInfo<span style="font-family:宋体;">对象的析构发生。最后,</span>main<span style="font-family:宋体;">l束后,?/span>GetStaticAllocator()<span style="font-family:宋体;">函数内的内存分配器的析构函数l一释放所有反信息占用的内存。最后,附上一个例?/span></p><div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">    </span><span style="color: #0000FF; ">struct</span><span style="color: #000000; "> Student<br />    {<br />        </span><span style="color: #008000; ">//</span><span style="color: #008000; ">ClassCat表示为Student的基c,为空c,所以Student可以l承它,但是代码上又不需要明承它Q非侵入式的基类?br />        </span><span style="color: #008000; ">//</span><span style="color: #008000; ">ClassCat提供二进制序列化操作Qxml序列化,json序列化,数据库序列化{操?/span><span style="color: #008000; "><br /></span><span style="color: #000000; ">        PPInlineClassTI(ClassCat, Student, ti)<br />        {<br />            PPReflAField(ti, name);<br />            PPReflAField(ti, age);<br />            PPReflAField(ti, sex, { kAttrXmlIgnore });    </span><span style="color: #008000; ">//</span><span style="color: #008000; ">表示不参与xml的序列化操作</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">        }<br />        AString name;<br />        </span><span style="color: #0000FF; ">int</span><span style="color: #000000; "> age;<br />        </span><span style="color: #0000FF; ">bool</span><span style="color: #000000; "> sex;<br />    };<br />    </span><span style="color: #0000FF; ">struct</span><span style="color: #000000; "> Config : Student<br />    {<br />        PPInlineClassTI(Student, Config, ti)<br />        {<br />            PPReflAField(ti, map);<br />        }<br />        HashMap</span><span style="color: #000000; "><</span><span style="color: #000000; ">U8String, </span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">></span><span style="color: #000000; "> map;<br />    };</span><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">   </span><span style="color: #000000; "><br /></span></div><p style="text-indent:21.0pt"><span style="font-family:宋体;"></span></p><p style="text-indent:21.0pt"><span style="font-family:宋体;">下期的主角是非R入式接口Q彻底替?/span>c++<span style="font-family:宋体;">上的多承,功能q远好过</span>C#<span style="font-family:宋体;">?/span>java<span style="font-family:宋体;">杂碎的弱鸡接口,更超狗语言的不知所谓的非R入式接口。如果仅仅是完备的反信息,而缺乏非侵入式接口,?/span>c++<span style="font-family:宋体;">下搞面向对象Q其实还是很痛苦的。但是,有了非R入式接口之后Q一切豁然开朗。甚臛_以说Q感?/span>c++<span style="font-family:宋体;">里面搞那么多玩意Q都不过是ؓ了给非R入式接口造势。然而非侵入式接口一直未曾正式诞生过?/span></p><img src ="http://www.shnenglu.com/huaxiazhihuo/aggbug/215082.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/huaxiazhihuo/" target="_blank">华夏之火</a> 2017-07-11 11:56 <a href="http://www.shnenglu.com/huaxiazhihuo/archive/2017/07/11/215082.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>stl的抽象缺Ll?/title><link>http://www.shnenglu.com/huaxiazhihuo/archive/2017/07/10/215076.html</link><dc:creator>华夏之火</dc:creator><author>华夏之火</author><pubDate>Mon, 10 Jul 2017 10:30:00 GMT</pubDate><guid>http://www.shnenglu.com/huaxiazhihuo/archive/2017/07/10/215076.html</guid><wfw:comment>http://www.shnenglu.com/huaxiazhihuo/comments/215076.html</wfw:comment><comments>http://www.shnenglu.com/huaxiazhihuo/archive/2017/07/10/215076.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/huaxiazhihuo/comments/commentRss/215076.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/huaxiazhihuo/services/trackbacks/215076.html</trackback:ping><description><![CDATA[<p style="text-indent:21.0pt"><span style="font-family:宋体;">古龙说过Q一个h的最大优点往往是其致命的q。这句话用在</span>stl<span style="font-family:宋体;">的P代器上,最是合适不q?/span>stl<span style="font-family:宋体;">通过q代器来解耦容器与法Q可谓击节赞叹;但是Q让q代器满世界的到处ؕ跑,未免大煞风景。此话怎讲Q?/span></p> <p style="text-indent:21.0pt"><span style="font-family:宋体;">其实Q有些语a没有P代器的概念,q且q活得很优雅Q好?/span>haskell<span style="font-family:宋体;">?/span>list<span style="font-family:宋体;">啊?/span>tree<span style="font-family:宋体;">啊,压根׃需要什么P代器Q只需要模式匹配,体现其数据结构的递归特点Q就可以很优雅地表达法。就?/span>java<span style="font-family:宋体;">?/span>c#<span style="font-family:宋体;">?/span>C++<span style="font-family:宋体;">q几个破面向对象语言Q才需要大用特用P代器Q没有P代器活不下M。P代器的出现就是ؓ了I补其语言丧失清晰表达递归数据l构的能力。看?/span>haskell<span style="font-family:宋体;">?/span>list<span style="font-family:宋体;">?/span>c++<span style="font-family:宋体;">?/span>stl<span style="font-family:宋体;">下的对应样子Q很多h都表C很难过Q因?/span>stl<span style="font-family:宋体;">里面Q?/span>list<span style="font-family:宋体;">Ҏ没?/span>tail<span style="font-family:宋体;">函数Q更逞论支持</span>list<span style="font-family:宋体;">?/span>tail<span style="font-family:宋体;">q是一?/span>list<span style="font-family:宋体;">q样l妙?/span>idea<span style="font-family:宋体;">。一切必通过q代器这个万金a来糊弄其尬的困境?/span></p> <p style="text-indent:21.0pt"><span style="font-family:宋体;">随便来看看几?/span>stl<span style="font-family:宋体;">法函数的代?/span><br /></p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><span style="color: #000000; ">Vector</span><span style="color: #000000; "><</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">></span><span style="color: #000000; "> nums </span><span style="color: #000000; ">=</span><span style="color: #000000; "> {..};<br />find(nums.begin(), nums.end(), </span><span style="color: #000000; ">2</span><span style="color: #000000; ">);<br />remove_if(nums.begin(), nums.end(), _1 </span><span style="color: #000000; ">>=</span><span style="color: #000000; "> </span><span style="color: #000000; ">0</span><span style="color: #000000; ">); </span><span style="color: #008000; ">//</span><span style="color: #008000; ">Z省事Q用了bll的风|在c++11中,要从零开始造一个bll风格的轮子,不能更方便,大概也就两三百行的代?/span></div><p style="text-indent:21.0pt"><span style="font-family:宋体;">看到没有Q你信不信,随便l计一下,一打的</span>algorithm<span style="font-family:宋体;">函数Qv码就?/span>12<span style="font-family:宋体;">个函数的调用之道Q必M?/span>container.begin()<span style="font-family:宋体;">Q?/span>container.end()<span style="font-family:宋体;">?/span>begin<span style="font-family:宋体;">?/span>end<span style="font-family:宋体;">q对兄弟QL成双成对的出玎ͼ说明了一件事情,是从一开始,它们必须被打包在一P而不应该生生地它们拆开。知道这一拆开Q带来多问题吗Q代码上的篏赘还是事Q比如,z清晰流畅的</span>find(nums, 2)<span style="font-family:宋体;">Q却要生的写成</span>find(nums.begin(), nums.end(), 2)<span style="font-family: 宋体;">。当Ӟq种</span>api<span style="font-family:宋体;">设计Q也q一无是处,LQ在表达容器里面的部分区间时Q很方便Q好比下面的代码</span></p> <p>int nums[10] = {…};</p> <p>find(nums+1, end(nums)-1, 2);</p> <p style="text-indent:21.0pt"><span style="font-family:宋体;">看v来,好像的确挺方便的Q将</span>begin<span style="font-family:宋体;">?/span>end<span style="font-family:宋体;">攑֜一P要表达这L概念Q似乎就有些ȝQ但其实Q这是假象,当角度变换时Q我们可以会有更方便的方式来表达q样的需求。最LQ容器的部分区间也应该是由容器本w来表达Q而不应{嫁给q代器来应付Q数l的部分也是数组Q树的分支也是树Q这L概念Q就应该由容器本w来定义。像是哈希表׃支持部分区间的概c?/span></p> <p style="text-indent:21.0pt"><span style="font-family:宋体;">Z</span>algorithm<span style="font-family:宋体;">的算法,全部Q不是基本)都要求一对P代器。那是因些算法的输入对象Q本来就是一个数据集合。而一个P代器无法完整地表达一个容器,L必须一对P代器才能完整地表达一个数据集。但是,用一对P代器来作为入参,和用一个区间作为入参,它所体现抽象的侧重点完全不同Q而由于此U不同,最后的演变l果Q也是天渊之别,x一对P代器设计思\是渊Q自Ӟ而区间的设计ҎQ显然是天?/span></p> <p style="text-indent:21.0pt"><span style="font-family:宋体;">再次回顾上文的结,</span>find<span style="font-family: 宋体;"><span style="Times New Roman";">Q?/span></span><span style="Times New Roman";">find_if</span><span style="font-family:宋体;"><span style="Times New Roman";">Q?/span></span><span style="Times New Roman";">remove, remove_copy, remove_copy_if, remove_if,……</span><span style="font-family:宋体;"><span style="Times New Roman";">Q?/span>有没有感受,一股浓的q程式风|十分的笨重,明显的非正交Q浓烈的</span>c<span style="font-family:宋体;">语言风格。对于这L</span>api<span style="font-family:宋体;">Q让本对委员会的那帮老不死,d的绝望了。他们(它们Q的审美观,停留在很低很低的层次上?/span></p> <p style="text-indent:21.0pt"><span style="font-family:宋体;">?/span>begin<span style="font-family:宋体;">Q?/span>end<span style="font-family:宋体;">拆分开来的最大问题,其实也就只是Q前一个函数的处理l果Q不能^滑的传递到下一个函数里面去。比如说Q现在函?/span>make_nums<span style="font-family:宋体;">q回</span>vector<int><span style="font-family:宋体;">Q试比较一下,高下立判?/span><br /></p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">auto nums </span><span style="color: #000000; ">=</span><span style="color: #000000; "> make_nums();<br />find(nums.begin(), nums.end(), </span><span style="color: #000000; ">2</span><span style="color: #000000; ">); </span><span style="color: #008000; ">//</span><span style="color: #008000; ">一对P代器作ؓ入参</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">find(make_nums(), </span><span style="color: #000000; ">2</span><span style="color: #000000; ">);</span><span style="color: #008000; ">//</span><span style="color: #008000; ">直接数据区间作ؓ入参</span></div><p style="text-indent:21.0pt"><span style="font-family:宋体;">说了q么多,我们强烈要求的仅仅是函数风格?/span>api<span style="font-family:宋体;">Q正交式的函数设计,前一个函数的处理l果可以qxC递给下一个函数。ȝ</span>algorithm<span style="font-family:宋体;">的一坨函敎ͼ本质上只需</span>filter<span style="font-family:宋体;">Q?/span>fold<span style="font-family:宋体;">Q?/span>map<span style="font-family:宋体;">Q?/span>insert(copy)<span style="font-family:宋体;">q屈指可数的几个函数可以自由地l合出来Qƈ且还能组合出?/span>algorithm<span style="font-family:宋体;">上没有的效果。首先,q几个函数的q回l果都是数据区的数据对象</span>(<span style="font-family:宋体;">里面?/span>begin<span style="font-family:宋体;">?/span>end<span style="font-family:宋体;">的成员函敎ͼ用以q回q代?/span>)<span style="font-family:宋体;">。其ơ,是在P代器上面做文章,以支?/span>filter<span style="font-family:宋体;">?/span>map<span style="font-family:宋体;">{操作,也就是在</span>*<span style="font-family:宋体;">?/span>++<span style="font-family:宋体;">?/span>!=<span style="font-family:宋体;">q几个运符上做花样Q要辑ֈ</span>filter<span style="font-family:宋体;">?/span>map<span style="font-family:宋体;">的效果,很容易的。至于像是要求随问P代器概念的函敎ͼ太常用的做?/span>array_view<span style="font-family:宋体;">里面好了Q或者就明确规定入参是</span>array_view<span style="font-family:宋体;">?/span></p> <p style="text-indent:21.0pt"><span style="font-family:宋体;">然后</span>stl<span style="font-family:宋体;">里面q臆造了一U好像叫?/span>insert_iterator<span style="font-family:宋体;">q代器类型的适配器,用以通过q代器的语法往容器里头插入数据Q好像很玄妙Q实则就是强行拔高P代器的用途,完全p背了q代器出现的初衷。这U扭曲的xQ完全就是上面那一坨病?/span>api<span style="font-family:宋体;">的物。所以,原本?/span>api<span style="font-family:宋体;">设计Q算法函数必M容器Q数据区_为入参,内部调用?/span>begin<span style="font-family:宋体;">?/span>end<span style="font-family:宋体;">成员函数获得q代器来遍历容器的函敎ͼ何其清晰的设计思\。但是,</span>stl<span style="font-family:宋体;">的设计思\Q导致P代器泛滥Q甚臌客户层面的代码也大把大把的P代器Q于是P代器的问题就接二q三的生,什么失效啊Q什?/span>first<span style="font-family:宋体;">?/span>last<span style="font-family:宋体;">匹对错误。还有,D容器里面的关于P代器的成员函数多了一倍,哈希表里面也没有cM?/span>C#<span style="font-family:宋体;">?/span>Dictionary<span style="font-family:宋体;">?/span>Keys<span style="font-family:宋体;">?/span>Values<span style="font-family:宋体;">属性函敎ͼq些用v来很方便的,不是吗?</span></p> <p style="text-indent:21.0pt">stl<span style="font-family:宋体;">的这U?/span>api<span style="font-family:宋体;">设计思\完全不是以方便用ؓ主,而是以满q独特口味为目的。看?/span>find<span style="font-family:宋体;">函数Q它q回一个P代器Q所以,我们使用Ӟ必须通过?/span>end<span style="font-family:宋体;">来判断要扄东西是否在区间里面,</span></p> <p><span>auto found = find(nums.begin(), nums.end(), 2);</span></p> <p>if (found != nums.end()){…}</p> <p style="text-indent:21.0pt"><span style="font-family:宋体;">依本座看Q直接就q回指针好了Q指针ؓ</span>nullptr<span style="font-family:宋体;">Q就表示元素找不刎ͼ代码变成q样</span></p> <p>if (auto found = find(nums, 2)){…}</p> <p style="text-indent:21.0pt"><span style="font-family:宋体;">代码合ƈ成一行,不用再和</span>end<span style="font-family:宋体;">比较了。更重要的是Q返回结果就是指针,cd非常明确Q可以^滑的传递到别的函数里;而不是P代器cdQ谁知道q代器类型是什么类型?/span>template<span style="font-family:宋体;">q种东西的类型,能明下来时Q就快明确下来。至于说Q有些区间的元素不支持返回地址Q好比,</span>vector<bool><span style="font-family:宋体;">Q很单,那就不支持好了。本座编?/span>c++<span style="font-family:宋体;">代码的原则之一Q不求大而全Q需求专一Q绝不会因ؓ个别同学Q就牺牲大多数情况下清晰方便高效?/span>api<span style="font-family:宋体;">风格。对于这些异敎ͼ必要Ӟ用奇技淫y解决。你知道Q因为多l承Q虚l承Q把成员函数指针q个z的概念搞得非常复杂Q不能按正常人方式来使用了,严重影响成员函数的用范围Q一直让本耿耿于怀。其实,</span>95%<span style="font-family:宋体;">以上的情况下Q我们就仅仅需要普通成员函数指针而已Q另外的</span>5%<span style="font-family:宋体;">Q也都可以用普通成员函数来装。所以,Z弥补q个遗憾Q本座做了一个精版的</span>delegate<span style="font-family:宋体;">Q只接受全局函数和普通成员函敎ͼ当字D?/span>object<span style="font-family:宋体;">为空Q就表示字段函数指针是全局函数Q不为空Q就表示函数指针是成员函数。至于其他一切奇奇怪怪的函数Q本座的q个</span>delegate<span style="font-family:宋体;">?/span>say no<span style="font-family:宋体;">Q明拒l?/span></p> <span style="font-size:10.5pt;font-family: "Calibri","sans-serif";Times New Roman";">stl</span><span style="font-size:10.5pt;font-family:宋体;Times New Roman";">的这U独特到处都是,</span><span style="font-size:10.5pt;font-family:"Calibri","sans-serif";Times New Roman";">boost</span><span style="font-size:10.5pt;font-family:宋体;Times New Roman";">更是其发扬光大Q反正设计出来的</span><span style="font-size:10.5pt;font-family:"Calibri","sans-serif";Times New Roman";">api</span><span style="font-size:10.5pt;font-family:宋体;Times New Roman";">Q就是不考虑让你用的舒爽Q二q制的布局Q更加一塌糊涂。比如,</span><span style="font-size:10.5pt;font-family:"Calibri","sans-serif";Times New Roman";">any</span><span style="font-size:10.5pt;font-family:宋体;Times New Roman";">的用,是这样子用的Q?/span><span style="font-size:10.5pt;font-family:"Calibri","sans-serif";Times New Roman";">cout << any_cast<int>(anyValue)</span><span style="font-size:10.5pt;font-family:宋体;Times New Roman";">Q这里还好,假如要分别针?/span><span style="font-size:10.5pt;font-family:"Calibri","sans-serif";Times New Roman";">any</span><span style="font-size:10.5pt;font-family:宋体;Times New Roman";">的实际类型来写代码,必须q样子:<br /></span><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(anyValue.type() </span><span style="color: #000000; ">==</span><span style="color: #000000; "> typeid(</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">))<br />    cout </span><span style="color: #000000; "><<</span><span style="color: #000000; "> any_cast</span><span style="color: #000000; "><</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">></span><span style="color: #000000; ">(anyValue);<br /></span><span style="color: #0000FF; ">else</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">if</span><span style="color: #000000; "> (anyValue.type() </span><span style="color: #000000; ">==</span><span style="color: #000000; "> typeid(</span><span style="color: #0000FF; ">double</span><span style="color: #000000; ">))<br />    cout </span><span style="color: #000000; "><<</span><span style="color: #000000; "> any_cast</span><span style="color: #000000; "><</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">double</span><span style="color: #000000; "> </span><span style="color: #000000; ">></span><span style="color: #000000; ">(anyValue);<br />…</span></div><span style="font-size:10.5pt;font-family:宋体;Times New Roman";"> </span><p style="text-indent:21.0pt"><span style="font-family:宋体;">q种对类型安全无理取闹的Q让人火冒三丈。要本_直接?/span>any<span style="font-family:宋体;">里面d</span>Cast<span style="font-family:宋体;">模板成员函数Q结果就q回指针好了Q指针ؓI,pC类型不匚wQ代码就变成q样</span></p><div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(auto value </span><span style="color: #000000; ">=</span><span style="color: #000000; "> anyValue.Cast</span><span style="color: #000000; "><</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">></span><span style="color: #000000; ">())<br />    cout </span><span style="color: #000000; "><<</span><span style="color: #000000; "> </span><span style="color: #000000; ">*</span><span style="color: #000000; ">value;<br /></span><span style="color: #0000FF; ">else</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(auto value </span><span style="color: #000000; ">=</span><span style="color: #000000; "> anyValue.Cast</span><span style="color: #000000; "><</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">double</span><span style="color: #000000; "> </span><span style="color: #000000; ">></span><span style="color: #000000; ">())<br />    cout </span><span style="color: #000000; "><<</span><span style="color: #000000; "> </span><span style="color: #000000; ">*</span><span style="color: #000000; ">value;<br />…<br /></span></div> <span style="font-size:10.5pt;font-family:宋体;Times New Roman";"> </span><p style="text-indent:21.0pt"><span style="font-family:宋体;">是否没那么心烦呢。另外,鉴于</span>stl<span style="font-family:宋体;">对于反射的拒l,采用</span>virtual+template<span style="font-family:宋体;">的类型拭擦大法来弥补Q其实ƈ不怎么完美。本座用反射重新实现?/span>any<span style="font-family:宋体;">Q比</span>stl<span style="font-family:宋体;">?/span>any<span style="font-family:宋体;">好多了,不管是性能、编译速度、用方便上Q都是要好太多。还有,</span>stl<span style="font-family:宋体;">?/span>any<span style="font-family:宋体;">Q要为每个用到的cd都要生成一个实实在在的多态具体类Q每个类都要有一个专门的虚函数表对应Q这些可都要写到二进制文仉面,代码是q样膨胀h的。MQ?/span>stl<span style="font-family:宋体;">回避反射后,反射׃另一UŞ式回归,好比</span>virtual+template<span style="font-family:宋体;">Q好?/span>%d<span style="font-family:宋体;">?/span>%s<span style="font-family:宋体;">Q好?/span>locale<span style="font-family:宋体;">的那?/span>facet<span style="font-family:宋体;">实现Q?/span> <span style="font-family:宋体;">q些动态机制各自ؓ政,各种混ؕ。还不如q脆׃源头上系l化公理化地l予l极解决?/span></p> <p style="text-indent:21.0pt"><span style="font-family:宋体;">所以,M上感?/span>stl<span style="font-family:宋体;">设计思\上存在的路线Q就是太在意?/span>c++<span style="font-family:宋体;">语言本n上的特点Q受语言自n的缺陷复杂媄响太多,忽略了真正的需求,太多的臆造需求,让需求来q就语言Q而不是让语言来配合基库的实际普遍需求,需求才是根本,Z可以最方便Q最清晰Q最性能的基库,完全可以大规模地使用宏、挖掘语a里面最黑暗的边角料Q甚至ؓ了库的清晰性,可以拒绝那些用了复杂Ҏ的数据l构Q比如多l承Q虚l承{无聊玩意?/span></p> <p><span style="font-family:宋体;">概括hQ\UK题导致最l的正果Q也x</span>stl<span style="font-family:宋体;">的具体弱鸡表现就是,最Ҏ是二q制接口使用上的重重ȝQ谁敢在动态库api使用stl的数据类型。其ơ是以下5点Q?/span></p> <p>1<span style="font-family:宋体;">、内存分配器不应该是容器的模板参敎ͼ?/span>allocator<span style="font-family:宋体;">的处理太q草率,当初q里必须做深入的挖掘Q?/span>c++<span style="font-family:宋体;">完全可以实现一定程度上的垃圑֛收功能,比如</span>arean allocator<span style="font-family:宋体;">Q不必一一回收?/span>arena allocator<span style="font-family:宋体;">上分配的对象Q只需一ơ性释?/span>arena allocator<span style="font-family:宋体;">的内存,辑ֈ多次分配Q一ơ释攄高性能效果Q还避免内存泄露Q也不用直接面对循环引用的怪胎设计问题。现有的内存理{略Q把压力都放在智能指针上Q?/span></p> <p>2<span style="font-family:宋体;">、提供的通用容器不够完备Q原?/span>stl<span style="font-family:宋体;">的数据结构就大可满所有正常和非正常的使用场合Q比如满R入式的链表需求,比如不管理元素生命周期的容器{;</span></p> <p>3<span style="font-family:宋体;">、过多的暴露q代器,q代器的应用范围q广Q?/span>stl<span style="font-family:宋体;">的算法函数用h很不方便Q?/span></p> <p>4<span style="font-family:宋体;">、回避动态类型反信息,Ҏ据的输入输出支持非常单薄Q包括字W串处理、文件读写、网l数据收发等Q标准库上的现有那点功能,仅仅是聊胜于无而已Q难堪大任;</span></p> <p>5<span style="font-family:宋体;">、非容器pȝ实用cd;</span></p> <p><span style="font-family:宋体;">一句话Q目?/span>stl<span style="font-family:宋体;">的用,q是q远不够爽。原本用?/span>stl<span style="font-family:宋体;">的代码,应该可以更短、更快、更。只可惜Q?/span>stl<span style="font-family:宋体;">在通过q代器实现算法与容器的分M后,停步不前,其设计体pd别的地方Q鲜有徏树创新。战略高度过于局促,很多复杂难搞的问题,其实都蕴含着l大的机遇,?/span>stl<span style="font-family:宋体;">都一一回避Q真是回避得好!</span></p> <span style="font-size:10.5pt;font-family:宋体;Times New Roman";"><br /></span><img src ="http://www.shnenglu.com/huaxiazhihuo/aggbug/215076.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/huaxiazhihuo/" target="_blank">华夏之火</a> 2017-07-10 18:30 <a href="http://www.shnenglu.com/huaxiazhihuo/archive/2017/07/10/215076.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://www.shnenglu.com/" title="精品视频久久久久">精品视频久久久久</a> <div class="friend-links"> </div> </div> </footer> <a href="http://www.z1568.cn" target="_blank">þۺϾƷһ </a>| <a href="http://www.591happy.cn" target="_blank">þþþþྫƷֱ</a>| <a href="http://www.3ponline.com.cn" target="_blank">91þþƷ˾þ</a>| <a href="http://www.hardwareman.cn" target="_blank">þþƷһ</a>| <a href="http://www.bev5l.cn" target="_blank">þþþþѹۿ</a>| <a href="http://www.85062.com.cn" target="_blank">þٸ۲AVר</a>| <a href="http://www.secwatch.com.cn" target="_blank">91Ʒɫ۾þ</a>| <a href="http://www.huochaipro.com.cn " target="_blank">ۺϾþþþþĻ޹ۺһ</a>| <a href="http://www.jdjx168.cn" target="_blank">ƷþþþþĻ </a>| <a href="http://www.yidasoft.com.cn" target="_blank">ƷþþþaӰԺ</a>| <a href="http://www.anrf.cn" target="_blank">þþƷһ</a>| <a href="http://www.dguv.cn" target="_blank">þˬһ </a>| <a href="http://www.qxmsv.cn" target="_blank">޾Ʒþþþ</a>| <a href="http://www.chindr-nb.cn" target="_blank">þþƷѹƬС</a>| <a href="http://www.bjwx2008.cn" target="_blank">뾫ƷþþӰ</a>| <a href="http://www.qcb8.cn" target="_blank">˺ݺۺϾþ</a>| <a href="http://www.jinlvyu1.cn" target="_blank">þþƷӰԺ</a>| <a href="http://www.jiudexn.cn" target="_blank">þþƷ޾Ʒɫ</a>| <a href="http://www.0769zc.net.cn" target="_blank">һAvëƬþþƷ</a>| <a href="http://www.galrw.cn" target="_blank">ľƷþþþùַ</a>| <a href="http://www.uqknet.cn" target="_blank">պƷþĻ</a>| <a href="http://www.lslvyekj.cn" target="_blank">޹Ʒþþþվ </a>| <a href="http://www.adpz.cn" target="_blank">Ļþҹ</a>| <a href="http://www.jianfeiyaow.cn" target="_blank">ݺݾƷþþĻ</a>| <a href="http://www.9503miwang.cn" target="_blank">ŷ޳ҹƷþ</a>| <a href="http://www.orange-cat.cn" target="_blank">þþþ</a>| <a href="http://www.qwoj.cn" target="_blank">ɫݺݾþۺ</a>| <a href="http://www.ddmes.cn" target="_blank">һAvëƬþþƷ</a>| <a href="http://www.sunriseydy.cn" target="_blank">Ʒ˾þþþӰԺ</a>| <a href="http://www.bbctp.cn" target="_blank">˾þƵ</a>| <a href="http://www.hedv.com.cn" target="_blank">þþùƷվ</a>| <a href="http://www.dgtspcb.com.cn" target="_blank">þøһëƬ</a>| <a href="http://www.ai385.cn" target="_blank">ҹþþþƷӰԺ</a>| <a href="http://www.szmry.cn" target="_blank">Ů㽶þ**ëƬƷ</a>| <a href="http://www.hwumbrella.cn" target="_blank">˾Ʒ׽þ69</a>| <a href="http://www.dnf-video.cn" target="_blank">ݲݾþþר</a>| <a href="http://www.pzjqfa.cn" target="_blank">þ99һ</a>| <a href="http://www.34lz.cn" target="_blank">Ʒþþþþþ</a>| <a href="http://www.legxcn.cn" target="_blank">˾þۺ</a>| <a href="http://www.yiyioo.cn" target="_blank">ĻۺϾþ2</a>| <a href="http://www.3hiis.cn" target="_blank">99þþƷһëƬ </a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>