被误解的C++——学习和使用

longshanks 2007-06-06 09:51:15
学习和使用
C++太复杂了。我猜想你一定是在计算机屏幕前不住地点头。其实我也在使劲的点头。没错,C++着实复杂,大概是迄今为止最复杂的语言。于是,便产生了一个推论:C++难学难用。
这句话也相当准确,但并非所有时候都这样。C++的学习和使用可以分为若干个层面,这些层面由简到繁,由易到难,分别适合不同层次的学习者和使用者。
先让我们来看看C++究竟有多复杂。我大致列了个清单,包括C++的主要语言特性。基本的一些特性,象变量、条件、选择等等,都掠去了,主要集中在体现C++复杂性的方面:
1. 指针。包括变量指针、函数指针等。可以计算。
2. 引用。包括变量的引用、函数的引用等。
3. 自由函数。
4. 类。包括具体类和抽象类。
5. 重载。包括函数重载和操作符重载。
6. 成员数据。包括static和非static的。
7. 成员函数。包括static和非static的。
8. 虚函数。包括对虚函数的override。
9. 继承。包括多继承、虚继承等。
10. 多态。包括动多态和静多态。
11. 类型转换。包括隐式的和显式的,以及臭名昭著的强制转换。
12. 模板。包括类模板和函数模板。
13. 模板特化。包括完全特化和部分特化。
14. 非类型模板参数。
15. 模板-模板参数。
我对照了C#的特性清单。C++比C#多的特性主要是:1、2、3、9的多继承、10的静多态、13、14、15。
而C#比C++多的特性主要有(这里没有考虑C++/CLI,C++/CLI补充了标准C++):
1. for each关键字。
2. as、is关键字。
3. seal关键字。
4. abstract关键字。
5. override/new关键字。
6. using关键字的一些补充用法。
7. implicit/explicit关键字。(C++有explicit关键字,但只用于构造函数)
8. interface关键字。
9. property。
10. delegate。
我们来分析一下。C++比C#所多的特性集中在编程技术方面,特别是编程模式,如由模板带来泛型编程和元编程机能。在OOP方面,C++走得更远,更彻底,主要表现在多继承和操作符重载方面。在传统的编程技术上,C++区分了对象和对象的引用(指针和引用)。而C#所有引用对象所持的都是引用。最后,C++拥有自由函数。
反过来再看C#,C#所多的都是些关键字。这些关键字都集中在OOP方面,并且都是以使编程技术易于理解为目的的。很多人(包括我在内)都希望C++也拥有C#的这些关键字(至少部分)。但与一般人的理解不同,C++标准委员会实际上是被编译器开发商所把持着,他们对引入关键字尤其神经过敏。没有办法,现实总是有缺憾的。
从这些方面可以看出,C++在编程机制上远远多于C#(Java的机制甚至更少)。对于新入行的人而言,一口气吞下这些内容,足以把他们撑死。相反,C#增加的关键字有助于初学者理解代码的含义。这些就是C#和Java比C++易于学习(易于理解)的真正原因。
但是,必须要强调的是,C#和Java中易于学习和理解的是代码,而不是这些代码背后的技术原理和背景。
我看到过的绝大多数C#代码都充满了重复代码和大量switch操作分派。如果这些程序员充分利用C#和Java的OOP机制,这些严重的代码冗余可以消除一半。(如果C#和Java具备C++那样的泛型编程能力,则另一半也可以消除。)这些程序员都是在没有充分理解语言机制和OOP技术的情况下编写软件,事倍功半。
这种情况在C++也有发生,但相对少些。这大概是因为C++足够复杂,使得学习者产生了“不彻底理解C++就学不会C++,就用不了C++”的想法。这种想法有利有弊,利在于促使学习者充分理解语言和语言背后的技术,而弊在于它吓跑了很多人。实际上,我们一会儿就会看到,C++可以同C#和Java一样,可以在不理解其中原理的情况下,仅仅按照既定规则编程。当然我们不希望这样,这是不好的做法。但鉴于现在业界
的浮躁心态,我们也就入乡随俗吧。
注意了!下面这句话是最关键的,最重要的,也是被长期忽略的:C++之所以复杂,是为了使用起来更简单。听不明白!自相矛盾!胡说!别急,且听我慢慢道来。
(限于篇幅,我这里只给出最后一部分案例代码,完整的案例在我的blog里:)
有三个容器,c1、c2、c3。容器的类型和元素的类型都未知。要求写一个算法框架,把c1里的元素同c2里的元素进行某种运算,结果放到c3里。
由于容器类型未知,必须使用所有容器公共的接口。所以,我写下了如下的C#代码:
public delegate void alg<T1, T2, R>(T1 v1, T2 v2, R r);
public static void Caculate_Contain<C1, T1, C2, T2, C3, T3>
(C1 c1, C2 c2, C3 c3, alg<T1, T2, T3> a )
where C1: IEnumerable<T1>
where C2 : IEnumerable<T2>
where C3 : IEnumerable<T3>
{
IEnumerator<T1> eai1 = c1.GetEnumerator();
IEnumerator<T2> eai2 = c2.GetEnumerator();
IEnumerator<T3> eai3 = c3.GetEnumerator();

while (eai1.MoveNext() && eai2.MoveNext() && eai3.MoveNext())
{
a(eai1.Current, eai2.Current,eai3.Current);
}
}
//使用
public static void CaculThem(int v1, int v2,int r) {
r=v1*v2;
}
Caculate_Contain(ai1, ai2, ai3, new alg<int, int, int>(CaculThem));
public static void CaculThem2(float v1, int v2,double r) {
r=v1*v2;
}
Caculate_Contain(af1, ai2, ad3, new alg<float, int, double>(CaculThem2));
我使用了一个委托,作为传递处理容器元素的算法的载体。使用时,用具体的算法创建委托的实例。但具体的算法CaculThem()必须同相应的容器元素类型一致。
下面轮到C++:
template<typename C1, typename C2, typename C3, typename Alg>
Caculate_Container(const C1& c1, const C2& c2, C3& c3, Alg a)
{
transform(c1.begin(), c1.end(), c2.begin(), c3.begin(), a);
}
//使用
template<typename T1, typename T2, typename R>
R mul_them(T1 v,T2 u) {
return v*u;
}
Caculate_Container(ai1, ai2, ai3, mul_them<int, int, int>);
Caculate_Container(af1, ad2, ad3, mul_them<float, double, double>);
如果容器元素有所变化,C#代码必须重写算法CaculThem()。但C++不需要,由于mul_them<>()本身是个函数模板,那么只需将这个函数模板用新的类型实例化一下即可。
C++的代码相对简单些,灵活性也更高些。但这还不是全部,C++还有一个最终极的解法,不需要循环,不需要创建模板算法,不需要写操作函数:
transform(c1.begin(), c1.end(), c2.begin(), c3.begin(), _1*_2);
...全文
17788 385 打赏 收藏 转发到动态 举报
写回复
用AI写文章
385 条回复
切换为时间正序
请发表友善的回复…
发表回复
huke3014 2011-11-14
  • 打赏
  • 举报
回复
热闹!`
return0x0 2008-04-12
  • 打赏
  • 举报
回复
这个楼好高啊~!

刚好占个386楼

争取冲向486、奔腾
zsxcn 2008-04-12
  • 打赏
  • 举报
回复
虽然我的东西不懂,但是还要顶
leozlin 2008-04-12
  • 打赏
  • 举报
回复
准备学习中,希望以后能学的好!为自己加油!
f22fbi 2008-04-10
  • 打赏
  • 举报
回复
mark学习
wuyecandi 2008-04-10
  • 打赏
  • 举报
回复
好东西
zmzbs123 2008-04-10
  • 打赏
  • 举报
回复
我也非常喜欢C++,哈哈
Who_know_me 2008-04-10
  • 打赏
  • 举报
回复
[Quote=引用 131 楼 zaxzab 的回复:]
学习 拼命赶上
[/Quote]
myullian 2008-04-10
  • 打赏
  • 举报
回复
好帖
gh880507 2008-04-10
  • 打赏
  • 举报
回复
强哦``!!!
好贴就要回``!
qqwaqq 2008-04-08
  • 打赏
  • 举报
回复
强贴,好贴,看了很多打击C++的贴后,终于见到了一个支持C++的了。
gaofen115 2008-04-01
  • 打赏
  • 举报
回复
so nice!楼主确实了解啊!小弟初来乍到,也在学习c++,我还是个大三学生,希望以后可以进入开发者的行列,和各位一起体验编程的乐趣!我建了个qq群46585285,希望大家有相同爱好的可以进来一起交流。
lily604 2008-04-01
  • 打赏
  • 举报
回复
c++这么多高级的功能不都是有库的支持吗,为什么没人给c#和java也编出这样的库来.个人觉得这些语言的难度平均是一样的,就像楼主说的使用boost库要达到很高的层次.到达的这个层次所付出的努力和学习c#或java的语法加上实现功能的算法应该是需要付出平均相同的努力的.主要就是编程思想的问题.比如opp.
add08 2008-04-01
  • 打赏
  • 举报
回复
顶一下
Soulic 2008-04-01
  • 打赏
  • 举报
回复
还是个菜鸟,学习了
lily604 2008-03-31
  • 打赏
  • 举报
回复
引用26楼
C++领域似乎总有一些人高高在上,当你觉得自己正在成长为一个语言大师(我想这个称号只存在于C++中)的时候,却发现自己其实连一个学徒都算不上。
.........................

我还不知道什么时候能体会到他所说的呢,努力......
WuBill 2008-03-31
  • 打赏
  • 举报
回复
就程序设计语言来说,远没有最好的,只有更好的,或者说只有更合适的。
能解决问题的都是好方法或是好语言。
VB、Delphi、C++、Java、C# 等语言各有所长,真的难分优劣。
开发人员应该根据客观条件,选择自己熟悉的语言,不要发誓忠于某某主义而自寻烦恼。
xqzl 2008-03-25
  • 打赏
  • 举报
回复
学过c++的,无论深浅,都喜欢发帖炫耀,故弄玄虚或一味贬低别人,这不是学习精神!
看codeproject上文章,比这里舒服!
bbsdkjdx 2008-02-28
  • 打赏
  • 举报
回复
通过http://blog.sina.com.cn/s/print_4ce1eaa7010008r4.html的报道,F22用的ADA,F35用的C++.
liveforme 2008-01-02
  • 打赏
  • 举报
回复
加载更多回复(365)

64,650

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧