现在的位置: 首页 > 综合 > 正文

驳斥《C++/CLI 的十宗罪》

2018年04月27日 ⁄ 综合 ⁄ 共 3944字 ⁄ 字号 评论关闭

由于公司有大批程序员死在 C/C++ 的内存管理上(泄露,越界),作为有先见之明的,伪程序员的老板征集了各方意见后,决定将现有的所有框架代码移植到 C++/CLI 下面来。由于本人在 C/C++ 上多花了几年功夫,自然,这个“简单”的问题就落在了我的肩膀上。用了一端时间 C++/CLI 后,发觉 C++/CLI 不是鼓吹中的那么好,特别是对于 C++ 程序员来说,简直是噩梦。依据 MS 的历史,我认为 MS 在 VC9.0 以后的版本中才能将 C++/CLI 实现的比较完美。(MS 的历史:要在第三个版本才会比较好用,例如:VC4、VC5 都不是很好,VC6 我用了 7 年;.NET 2002、2003 也一堆问题,.NET 2005 终于好用了)。

特在此总结了 C++/CLI 的十宗罪,罪状如下:

第一、没有全局变量

  好吧,我承认“现代”的高级语言都没有全局变量,不过,实现这些高级语言的运行库都有无数的全局变量(反汇编跟踪下就知道了)——哦,只许州官放火,不许百姓点灯。好吧,我承认没有全局变量,我还能生存,大不了晚上我不点灯不做事了。

[Comments] 既然你知道现代的高级语言都没有全局变量,怎么能把它作为C++/CLI的罪过呢?为什么现代的高级语言都没有全局变量呢?为什么面向对象的一大特点就是封装性呢?既然你研究了几年了C/C++,应该清楚和明白吧?简单的来说,在C语言时代是没有封装性的概念的,因此全局变量满天飞,使得大型程序维护起来十分的不方便。这也是为什么面向对象概念兴起的一个很重要的原因。作为一个程序员如果从整体的设计来考虑的话,是应该尽量少用或者不用全局变量的。这也是为什么现代的高级语言都取消了全局变量了,而且如果面向对象的设计能力比较强的话,是可以完全的抛弃全局变量的使用的。当然了,对于很多C程序员来说,不能使用全局变量有点要命的感觉。不过这不能怨语言,应该看看自己是否真正理解了面向对象的概念。

还有就是,为什么他们的运行库有无数全局变量?因为他们是用C来实现的,在C语言里是必须要用全局变量的。

第二、类的静态成员变量的初始化时机问题

  没有全局变量是吧,那么我用静态成员变量来模拟总可以了吧。很好,顺利编译通过!但是,但是,这个静态成员变量是什么时候初始化的呢?哦,用到这个类的任何变量/函数/实例的时候初始化的!这个到是很好,解决了全局变量的初始化顺序问题。问题是,我只不过希望静态成员变量将本类注册到类工厂去。我从来不会直接访问这个类的任何变量/函数/实例——我只访问他的基类。这样一来,我的类工厂里空空如野,我的系统再也工作不起来了。

[Comments]这个问题跟第一个问题是类似的。还是你要想方设法的去用全局变量,而没有想过为什么不让你用全局变量。静态成员变量本来就不是做这个用途的,它是类的实例的一个全局变量,注意只是这个类的实例,而不是整个应用程序。这只能说明你错用了静态成员,而不能归于C++/CLI的罪过。

还有就是静态成员完全可以初始化,只是你自己不会罢了。建议你好好的去学习一下.NET。

第三、弱智的、缺乏实际应用经验的人设计的的静态成员变量初始化地方的问题

  你能判断下面这句话是变量声明还是函数申明吗?
static int myfunc(mytype_or_myvar);
反观 C++ 的做法:
static int myfunc;
int myclass::myfunc(mytype_or_myvar);
你会有歧义吗?

[Comments]没看出这个有什么问题呀?你难道读程序是一句一句的读吗?我们怎么能够把程序分割理解呢?如果上下文一起来看,能有什么歧义呢?

第三、静态局部变量的问题

  你知道,仅仅一个“单件”,就多么的需要这个玩意!

[Comments]这个不太明白想表达什么。

第四、功能弱到极点的 array

  其实已经很强大了,比 C++ 的数组多了一个 Resize() 功能了。但是,跟 std::vector 比较起来,一个天上,一个地狱!好吧,我承认我对 CLI 不熟悉,那么,谁告诉我,C++/CLI 提供了什么样的东西,具备 std::vector 的功能?不要告诉我基于 CLI 的模板库,我严重怀疑其可工作否。

[Comments]看来你真的没好好学过C++/CLI,你不知道C++/CLI最大的优点在于通吃一切吗?你现在抱怨的是CLI,就算CLI没有你想要的功能。可是C++/CLI是C++和CLI的混合体,你没有必要一定用CLI,你当然还可以用回你所有的C++功能。std::vector算个什么呢?

第五、value struct 和 cpp struct 在模板函数上,对“引用”的符号匹配问题

  对于 cpp struct 应该匹配那个符号?'&' 还是 '%'?答案是 '%'。哦,我的天哪,居然还可以使用 pin_ptr<cpp struct> 来取地址!实在是太伟大了!那么,我的 cpp struct 变量究竟位于哪里?堆上?栈上?还是托管堆上?我迷糊了,编译器跟我一起迷糊了。

[Comments] 看来你还没分清楚cpp struct和CLI struct的区别呀。建议你还是好好学习一下再来讨论吧。

第六、模板函数的特例化问题

  对于下面这样的函数:
ref class myclass
{
         template<typename T>
         myclass % operator << (T % t){...}            // 函数一
         myclass % operator << (mytype % t){...} // 函数二
};

myclass c;
mytype t;
c << t;   // 式一

  你认为“式一”会调用那个函数?我知道你的答案,不过你的答案是错误的,因为你是一个资深的 C++ 程序员。当我意识到我的系统不能正常工作是源于此的时候,我很想联系恐怖份子,购置一枚或者更多的原子弹,然后在 google 上找到 MS 总部甚至分部的坐标,然后把原子弹的目标设置好……

[Comments] 建议你先学学template和generic的区别吧。

第七、C++ 和 C++/CLI 的代沟问题

  ref class,value class 里不能放置 cpp class 的实例,这个我还能接受。但是,cpp class 里不能放置 ref class,value class 的任何玩意——实例、引用、指针、interior_ptr,pin_ptr。我怎么实现回调式的功能?不是我非要设计出回调式的功能,而是,有那么多,那么多的Win32 API 是回调式的!好在我在知识的海洋中找到了 System::Runtime::InteropServices::GCHandle,不然,我定制的原子弹就会上升成为氢弹!

[Comments] 这不是C++和C++/CLI的代沟问题,是C++和CLI的代沟问题,C++/CLI提供了你一个桥梁把他们联系在一起,你应该感激才对。没有C++/CLI你更没法搞。这是C++/CLI一大优点,而不是罪过。

第八、.NET提供的类库太过于臃肿

  大家知道,C/C++ 的 CRT 也就几百K,C/C++ 仍然实现了你所能看到的软件的绝大部分——但是,你看到的,用 .NET 实现的软件有几个?好吧,我承认我偷梁换柱,不过,由于.NET库的臃肿,以致于稍微一个好听,合义的单词都被.NET用掉了。这让我不能放心用 Object,String,IStream...等等作为我自己的类型的命名,我只好绞尽脑汁想别的名字——正如您所猜测的一样,我的英文很差,必须要借助翻译工具才能看懂 C++/CLI 的白皮书。这让我想出新鲜的,上口的,其他跟我英文一样差的人能看明白的单词,其难度真不啻于用随机数拼出一个Windows啊!

  随机数拼出一个Windows:这个是我一个哥们的研究课题,把 N 台电脑关在一个小黑屋里,让他们随机生成二进制数据,并当作程序来运行。当速度足够快或者运气足够好的时候,生成的二进制数据刚好跟你从 DB 商手里买到的 Window XP 一样。(UMU:U墨的手法,说明几率极小极小!)

[Comments]首先.NEt是否臃肿,是否应该臃肿本身就是一个问题。就算.NET是臃肿的,也不是C++/CLI的罪过。那是.NET的问题。

 

第九、四饼!

  这个问题是由第八个问题引起的,因为有这么多,这么深的名字空间,各个名字空间下有这么多相同名字的类型名,让我不得不整天::...::...::...::...::...::...::...::...::...::...::...::...::......
真的,四饼占了我代码的十分之一的字数。如果按字数发工资,我是乐意的,问题是,不是按字数发工资!

[Comments]如果你用了using spacename, 是不用那么多::的,这个是.NET的常识问题,也是.NET的一大预言特点。优于C++的。

第十、GC不能解决内存泄露问题

  首先,我们要承认 GC 的一个伟大壮举:GC 能够在程序退出去的时候,释放所有的内存。但是,在 8 年前,我用 C 在 DOS 也能够办到这个功能。问题是,运行十天后,我 C/C++ 占用的不会释放的内存,GC 也不能释放,甚至 GC 占用的内存还更多。因为 GC 分不清楚没有置空的句柄是否还有机会被再次使用。

[Comments] 看来你一点都不懂GC呀。建议你先去好好学学。

综上所述,作者是一个对.NET没有太多概念的C/C++的程序员。因此,对C++/CLI的理解,就显得非常肤浅了。不知道作者搞了几年的C/C++为什么就这么轻率的发表这样不负责任,有很大误导作用的文章出来。从作者这样热衷全局变量的使用来看,好像面向对象的设计水平也很普通。希望大家不要被误导,看到作者的文章,使我对C++/CLI更加有信心了。

 

抱歉!评论已关闭.