初学者应当如何学习C++以及编程.docx_第1页
初学者应当如何学习C++以及编程.docx_第2页
初学者应当如何学习C++以及编程.docx_第3页
初学者应当如何学习C++以及编程.docx_第4页
初学者应当如何学习C++以及编程.docx_第5页
已阅读5页,还剩18页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Javascript是世界上最受误解的语言,其实C+何尝不是。坊间流传的错误的C+学习方法一抓就是一大把。我自己在学习C+的过程中也走了许多弯路,浪费了不少时间。为什么会存在这么多错误认识?原因主要有三个,一是C+语言的细节太多。二是一些著名的C+书籍总在(不管有意还是无意)暗示语言细节的重要性和有趣。三是现代C+库的开发哲学必须用到一些犄角旮旯的语言细节(但注意,是库设计,不是日常编程)。这些共同塑造了C+社群的整体心态和哲学。单是第一条还未必能够成气候,其它语言的细节也不少(尽管比起C+起来还是小巫见大巫),就拿Javascript来说,作用域规则,名字查找,closure,for/in,这些都是细节,而且其中还有违反直觉的。但许多动态语言的程序员的理念我猜大约是学到哪用到哪罢。但C+就不一样了,学C+之人有一种类似于被暗示的潜在心态,就是一定要先把语言核心基本上吃透了才能下手写出漂亮的程序。这首先就错了。这个意识形成的原因在第二点,C+书籍。市面上的C+书籍不计其数,但有一个共同的缺点,就是讲语言细节的书太多C+ gotchas,Effective C+,More Effective C+,但无可厚非的是,C+是这样一门语言:要拿它满足现代编程理念的需求,尤其是C+库开发的需求,还必须得关注语言细节,乃至于在C+中利用语言细节已经成了一门学问。比如C+模板在设计之初根本没有想到模板元编程这回事,更没想到C+模板系统是图灵完备的,这也就导致了Modern C+ Design和C+ Template Metaprogramming的惊世骇俗。这些技术的出现为什么惊世骇俗,打个比方,就好比是一块大家都认为已经熟悉无比,再无秘密可言的土地上,突然某天有人挖到原来地下还蕴藏着最丰富的石油。在这之前的C+虽然也有一些细节,但也还算容易掌握,那可是C+程序员们的happy old times,因为C+的一切都一览无余,everything is figured out。然而Modern C+ Design的出世告诉人们,“瞧,还有多少细节你们没有掌握啊。”于是C+程序员们久违的激情被重燃起来,奋不顾身的踏入细节的沼泽中。尤其是,模板编程将C+的细节进一步挖掘到了极致我们干嘛关心涉及类对象的隐式转换的优先级高低?看看boost:is_base_of就可以知道有多诡异了。但最大的问题还在于,对于这些细节的关注还真有它合适的理由:我们要开发现代模板库,要开发active library,就必须动用模板编程技术,要动用模板编程技术,就必须利用语言的犄角旮旯,enable_if,type_traits,甚至连早就古井无波的C宏也在乱世中重生,看看boost:preprocessor有多诡异就知道了,连C宏的图灵完备性(预编译期的)都被挖掘出来了。为什么要做这些?好玩?标榜?都不是,开发库的实际需求。但这也正是最大的悲哀了。在boost里面因实际需求而动用语言细节最终居然能神奇的完成任务的最好教材就是boost:foreach,这个小设施对语言细节的发掘达到了惊天地泣鬼神的地步,不信你先试着自己去看看它的源代码,再看看作者介绍它的文章吧。而boost:typeof也不甘其后C+语言里面有太多被“发现”而不是被“发明”的技术。难道最初无意设置这些语言规则的家伙们都是Oracles?因为没有variadic templates,人们用宏加上缺省模板参数来实现类似效果。因为没有concepts,人们用模板加上析构函数的细节来完成类似工作。因为没有typeof,人们用模板元编程和宏加上无尽的细节来实现目标 C+开发者们的DIY精神不可谓不强。然而,如果仅仅是因为要开发优秀的库,那么涉及这些细节都还是情有可原的,至少在C+09出现并且编译器厂商跟上之前,这些都还能说是不得已而为之。但我们广大的C+程序员呢?大众是容易被误导的,我也曾经是。以为掌握了更多的语言细节就更牛,但实际却是那些语言细节十有八九是平时编程用都用不到的。C+中众多的细节虽然在库设计者手里面有其用武之地,但普通程序员则根本无需过多关注,尤其是没有实际动机的关注。一般性的编码实践准则,以及基本的编程能力和基本功,乃至基本的程序设计理论以及算法设计。才是真正需要花时间掌握的东西。学习最佳编码实践比学习C+更重要。看优秀的代码也比埋头用差劲的编码方式写垃圾代码要有效。直接、清晰、明了、KISS地表达意图比玩编码花招要重要避免去过问任何语言细节,除非必要。这个必要是指在实际编程当中遇到问题,这样就算需要过问细节,也是最省事的,懒惰者原则嘛。一个掌握了基本的编程理念并有较强学习能力的程序员在用一门陌生的语言编程时就算拿着那本语言的圣经从索引翻起也可以编出合格的程序来。十年学会编程不是指对每门语言都得十年,那一辈子才能学几门语言哪,如果按字母顺序学的话一辈子都别指望学到Ruby了;十年学习编程更不是指先把语言特性从粗到细全都吃透才敢下手编程,在实践中提高才是最重要的。至于这种抠语言细节的哲学为何能在社群里面呈野火燎原之势,就是一个心理学的问题了。想像人们在论坛上讨论问题时,一个对语言把握很细致的人肯定能够得到更多的佩服,而由于论坛上的问题大多是小问题,所以解决实际问题的真正能力并不能得到显现,也就是说,知识型的人能够得到更多佩服,后者便成为动力和仿效的砝码。然而真正的编程能力是与语言细节没关系的,熟练运用一门语言能够帮你最佳表达你的意图,但熟练运用一门语言绝不意味着要把它的边边角角全都记住。懂得一些常识,有了编程的基本直觉,遇到一些细节错误的时候再去查书,是最节省时间的办法。C+的书,Bjarne的圣经The C+ Programming Language是高屋建瓴的。大规模C+程序设计是挺务实的。Accelerated C+是最佳入门的。C+ Templates是仅作参考的。C+ Template Metaprogramming是精力过剩者可以玩一玩的,普通程序员碰都别碰的。ISO.IEC C+ Standard 14882不是拿来读的。Bjarne最近在做C+的教育,新书是绝对可以期待的。P.S. 关于如何学习编程,g9的blog上有许多精彩的文章:这里,这里,这里,这里 实际上,我建议你去把g9老大的blog翻个底朝天 :P再P.S. 书单?我是遑于给出一个类似C+初学者必读这种书单的。C+的书不计其数,被公认的好书也不胜枚举。只不过有些书容易给初学者造成一种错觉,就是“学习C+就应该是这个样子的”。比如有朋友提到的高质量C/C+编程,这本书有价值,但不适合初学者,初学者读这样的书容易一叶障目不见泰山。实际上,正确的态度是,细节是必要的。但细节是次要的。其实学习编程我觉得应该最先学习如何用伪码表达思想呢,君不见Introduction to Algorithm里面的代码?TAOCP中的代码?哦,对了它们是自己建立的语言,但这种仅教学目的的语言的目的就是为了避免让写程序的人一开始就忘了写程序是为了完成功能,以为写程序就是和语言细节作斗争了。Bjarne说程序的正确性最重要,boost的编码标准里面也将正确性列在性能前面。此外,一旦建立了正确的学习编程的理念,其实什么书(只要不是太垃圾的)都有些用处。都当成参考书,用的时候从目录或索引翻,基本就对了。再再P.S. myan老大和g9老大都给出了许多精彩的见解。我不得不再加上一个P.S。具体我就不摘录了,如果你读到这里,请务必往下看他们的评论。转载者别忘了转载他们的评论:-)许多朋友都问我同一个问题,到底要不要学习C+。其实这个问题问得很没有意义。“学C+”和“不学C+”这个二分法是没意义的,为什么?因为这个问题很表面,甚至很浮躁。重要的不是你掌握的语言,而是你掌握的能力,借用myan老大的话,“重要的是这个磨练过程,而不是结果,要的是你粗壮的腿,而不是你身上背的那袋盐巴。”。此外学习C+的意义其实真的是醉翁之意不在酒,像C/C+这种系统级语言,在学习的过程中必须要涉及到一些底层知识,如内存管理、编译连接系统、汇编语言、硬件体系结构等等等等知识(注意,这不包括过分犄角旮旯的语言枝节)。这些东西也就是所谓的内功了(其实最最重要的内功还是长期学习所磨练出来的自学能力)。对此大嘴Joel在Joel On Software里面提到的漏洞抽象定律阐述得就非常漂亮。所以,答案是,让你成为高手的并不是你掌握什么语言,精通C+未必就能让你成为高手,不精通C+也未必就能让你成为低手。我想大家都不会怀疑g9老大如果要抄起C+做一个项目的话会比大多数自认熟练C+的人要做得漂亮。所以关键的不是语言这个表层的东西,而是底下的本质矛盾。当然,不是说那就什么语言都不要学了,按照一种曹操的逻辑,“天下语言,唯imperative与declarative耳”。C+是前者里面最复杂的一种,支持最广泛的编程范式。借用当初数学系入学大会上一个老师的话,“你数学都学了,还有什么不能学的呢?”。学语言是一个途径,如果你把它用来磨练自己,可以。如果你把它用来作为学习系统底层知识的钥匙,可以。如果你把它用来作为学习如何编写优秀的代码,如何组织大型的程序,如何进行抽象设计,可以。如果掉书袋,光啃细节,我认为不可以(除非你必须要用到细节,像boost库的coder们)。位域具体存放数值测试#include #include using namespace std;void main()struct test/在这里测试就可以发现其规律,有无unsigned、a:1 a:2 a:4 a:8 a:16 a:32 以及用char的各值来试验就可发现位域的规律unsigned int a:8;test t1;t1.a = 0;cout 0: dect1.aendl;cout 0: hext1.aendl;coutendl;t1.a = 1;cout 1: dect1.aendl;cout 1: hext1.aendl;coutendl;t1.a = 2;cout 2: dect1.aendl;cout 2: hext1.aendl;coutendl;t1.a = 3;cout 3: dect1.aendl;cout 3: hext1.aendl;coutendl;t1.a = 126;cout 126: dect1.aendl;cout 126: hext1.aendl;coutendl;t1.a = 127;cout 127: dect1.aendl;cout 127: hext1.aendl;coutendl;t1.a = 128;cout 128: dect1.aendl;cout 128: hext1.aendl;coutendl;t1.a = 129;cout 129: dect1.aendl;cout 129: hext1.aendl;coutendl;t1.a = 253;cout 253: dect1.aendl;cout 253: hext1.aendl;coutendl;t1.a = 254;cout 254: dect1.aendl;cout 254: hext1.aendl;coutendl;t1.a = 255;cout 255: dect1.aendl;cout 255: hext1.aendl;coutendl;t1.a = 256;cout 256: dect1.aendl;cout 256: hext1.aendl;coutendl;t1.a = 257;cout 257: dect1.aendl;cout 257: hext1.aendl;coutendl;t1.a = 258;cout 258: dect1.aendl;cout 258: hext1.aendl;coutendl;t1.a = 259;cout 259: dect1.aendl;cout 259: hext1.aendl;coutendl;t1.a = 260;cout 260: dect1.aendl;cout 260: hext1.aendl;coutendl;t1.a = 261;cout 261: dect1.aendl;cout 261: hext1.aendl;coutendl;t1.a = 262;cout 262: dect1.aendl;cout 262: hext1.aendl;coutendl;t1.a = 263;cout 263: dect1.aendl;cout 263: hext1.aendl;coutendl;t1.a = 264;cout 264: dect1.aendl;cout 264: hext1.aendl;coutendl;t1.a = 65533;cout 65533: dect1.aendl;cout 65533: hext1.aendl;coutendl;t1.a = 65534;cout 65534: dect1.aendl;cout 65534: hext1.aendl;coutendl;t1.a = 65535;cout 65535: dect1.aendl;cout 65535: hext1.aendl;coutendl;t1.a = 65536;cout 65536: dect1.aendl;cout 65536: hext1.aendl;coutendl;t1.a = 65537;cout 65537: dect1.aendl;cout 65537: hext1.aendl;coutendl;从STL中学习泛型编程最近在看数据结构方面的书籍,遇到了泛型编程方面的问题,以前遇到的泛型编程问题不多,大多数也已经遗忘,于是打算重新捡起来。下面一段关于泛型编程的定义摘抄于百度百科,应该能概括什么事泛型编程。泛型编程让你编写完全一般化并可重复使用的算法,其效率与针对某特定数据类型而设计的算法相同。泛型编程的代表作品STL是一种高效、泛型、可交互操作的软件组件。所谓泛型(Genericity),是指具有在多种数据类型上皆可操作的含意,与模板有些相似。STL巨大,而且可以扩充,它包含很多计算机基本算法和数据结构,而且将算法与数据结构完全分离,其中算法是泛型的,不与任何特定数据结构或对象类型系在一起。STL以迭代器 (Iterators)和容器(Containers)为基础,是一种泛型算法(Generic Algorithms)库,容器的存在使这些算法有东西可以操作。STL包含各种泛型算法(algorithms)、泛型指针(iterators)、泛型容器(containers)以及函数对象(function objects)。STL并非只是一些有用组件的集合,它是描述软件组件抽象需求条件的一个正规而有条理的架构。上面的概括只是从理论上解释了什么是泛型,可是看过后还是不知道怎么使用泛型,于是乎笔者找到了STL中定义的头文件,下面就一步一步解开泛型的秘密。由于原版的STL中很多类的套嵌,不便于解释,所以简化了STL,以下以vector容器为例:文件名:vector.h1: template /模板定义了Object类型,在使用的时候可以以任何类型代替此类型2: class vector3: 4: public:5: explicit vector( int initSize = 0 ) : theSize( initSize ), theCapacity( initSize + SPARE_CAPACITY )/重点注意构造函数的定义,构造函数支持两种方式初始化vector容器,这下知道怎么用vector了吧6: objects = new Object theCapacity ; 7: vector( const vector & rhs ) : objects( NULL )8: operator=( rhs ); 9: vector( )10: delete objects; 11:12: bool empty( ) const13: return size( ) = 0; 14: int size( ) const15: return theSize; 16: int capacity( ) const17: return theCapacity; 18:19: Object & operator( int index )20: 21: #ifndef NO_CHECK22: if( index = size( ) )23: throw ArrayIndexOutOfBoundsException( index, size( ) );24: #endif25: return objects index ;26: 27:28: const Object & operator( int index ) const29: 30: #ifndef NO_CHECK31: if( index = size( ) )32: throw ArrayIndexOutOfBoundsException( index, size( ) );33: #endif34: return objects index ;35: 36:37: const vector & operator = ( const vector & rhs );38: void resize( int newSize );39: void reserve( int newCapacity );40:41: / Stacky stuff42: void push_back( const Object & x );43: void pop_back( );44: const Object & back ( ) const;45:46: / Iterator stuff: not bounds checked47: typedef Object * iterator;48: typedef const Object * const_iterator;49:50: iterator begin( )51: return &objects 0 ; 52: const_iterator begin( ) const53: return &objects 0 ; 54: iterator end( )55: return &objects size( ) ; 56: const_iterator end( ) const57: return &objects size( ) ; 58:59: enum SPARE_CAPACITY = 16 ;60:61: private:62: int theSize;63: int theCapacity;64: Object * objects;65: ;文件名:vector.cpp1: template /模板定义了Object类型,在使用的时候可以以任何类型代替此类型2: const vector & vector:operator=( const vector & rhs )/重载赋值操作符3: 4: if( this != &rhs )/优化a=a的情况5: 6: delete objects;7: theSize = rhs.size( );8: theCapacity = rhs.theCapacity;9:10: objects = new Object capacity( ) ;11: for( int k = 0; k size( ); k+ )12: objects k = rhs.objects k ;13: 14: return *this;15: 16:17: /以下为一些常用操作函数的定义18:19: template 20: void vector:resize( int newSize )21: 22: if( newSize theCapacity )23: reserve( newSize * 2 );24: theSize = newSize;25: 26:27:28: template 29: void vector:reserve( int newCapacity )30: 31: Object *oldArray = objects;32:33: int numToCopy = newCapacity theSize ? newCapacity : theSize;34: newCapacity += SPARE_CAPACITY;35:36: objects = new Object newCapacity ;37: for( int k = 0; k numToCopy; k+ )38: objects k = oldArray k ;39:40: theSize = numToCopy;41: theCapacity = newCapacity;42:43: delete oldArray;44: 45:46:47: template 48: void vector:push_back( const Object & x )49: 50: if( theSize = theCapacity )51: reserve( 2 * theCapacity + 1 );52: objects theSize+ = x;53: 54:55:56: template 57: void vector:pop_back( )58: 59: if( empty( ) )60: throw UnderflowException( Cannot call pop_back on empty vector );61: theSize-;62: 63:64:65: template 66: const Object & vector:back( ) const67: 68: if( empty( ) )69: throw UnderflowException( Cannot call back on empty vector );70: return objects theSize - 1 ;71: 下面给出一个例子,大家可以结合标准库里的定义文件好好熟悉一下泛型编程(笔者的头文件与此例子的头文件定义不同,文章最后给出该例子的头文件定义):1: / constructing vectors2: #include 3: #include 4: using namespace std;5:6: int main ()7: 8: unsigned int i;9:10: / constructors used in the same order as described above:11: vector first; / empty vector of ints12: vector second (4,100); / four ints with value 10013: vector third (second.begin(),second.end(); / iterating through second14: vector fourth (third); / a copy of third15:16: / the iterator constructor can also be used to construct from arrays:17: int myints = 16,2,77,29;18: vector fifth (myints, myints + sizeof(myints) / sizeof(int) );19:20: cout The contents of fifth are:;21: for (i=0; i fifth.size(); i+)22: cout fifthi;23:24: cout endl;25:26: return 0;27: vector.h文件:1: class Vector : public Object, public Enumeration2: 3: protected:4:5: Object *vec;6: int elementCount;7: int elementData;8: int incrementSize;9: int readElements;10: void trim(); /*shrinks the vector */11: void resize(); /*resize the vector on a given incrementSize*/12:13: public:14: Vector(); /* Generic Constructor */15: Vector(int); /*Constructor with a given amount of Capacity */16: Vector(int, int); /* Constructor with a given amount of Capacity and incrementSize */17: Vector(Vector &); /*CopyConstructor */18: virtual Vector(); /* Generic Destructor */19: void addElement(Object *); /* Adds the specified component to the end of this vector */20: void setElementAt(Object *, int); /*Overwrites a given element at Position x */21: Object *elementAt(int); /* Returns the component at the specified index. */22: Enumeration *elements(); /* Returns an enumeration of the components of this vector. */23: bool hasMoreElements(); /* Tests if this enumeration contains more elements.*/24: Object *nextElement(); /* Returns the next element of this enumeration. */25: void insertElementAt(Object *, int);/* Inserts the specified object as a component in this vector at the specified index. */26: bool isEmpty(); /* Tests if this vector has no components. */27: bool removeElementAt(int); /* Deletes the component at the specified index. */28: bool removeElement(Object *); /*Deletes the last occurence of the given Object */29: virtual String toString(); /* Returns a string representation of this vector. */30: int size();31: void setIncrementSize(int);32: int getIncrementSize();33: int getElementCount();34: void ensureCapacity(int);35: virtual bool equals(Vector *);36: ;37:38: ostream &operatorConfiguration Properties-General-Character Set,选择”Use Unicode Character Set“就是使用Uncode字符集,选择” Use Multi-Byte Character Set“就是多字节字符集。 第二次中招,god,花了我好长时间才找到问题: 我在CodeProject上找了一个很厚道的老外写的一个继承了CDialog窗体类CResizableDial

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论