计算机是怎样跑起来的-第7章 成为会使用面向对象编程的程序员吧

计算机是怎样跑起来的-第7章 成为会使用面向对象编程的程序员吧
在本章笔者想让诸位掌握的是有关面向对象编程的概念。理解面向对象编程有着各种各样的方法,程序员们对它的观点也会因人而异。本章会将笔者至今为止遇到过的多名程序员的观点综合起来,对面向对象编程进行介绍。哪种观点才是正确的呢?这并不重要,重要的是把各个角度的观点整合起来,而后形成适合自己的理解方法。在读完本章后,请诸位一定要和朋友或是前辈就什么是面向对象编程展开讨论。
7.1 面向对象编程
面向对象编程(OOP,Object Oriented Programming)是一种编写程序的方法,旨在提升开发大型程序的效率,使程序易于维护 A。因此在企业中,特别是管理层的领导们都青睐于在开发中使用面向对象编程。因为如果开发效率得以提高、代码易于维护,那么就意味着企业可以大幅度地削减成本(开发费用+维护费用)。甚至可以这样说,即使管理者们并不十分清楚面向对象编程到底是什么,他们也还是会相信“面向对象编程是个好东西”。
但是在实际的开发工作中,程序员们却有一种对面向对象编程敬而远之的倾向。原因在于他们不得不重新学习很多知识,还会被新学到的知识束缚自己的想法,导致无法按照习惯的思维开发。以笔者写书的经验来看,如果是讲解传统的编程方法,那么只需要写一本书就够了,而讲解面向对象编程则需要写两本书。直说的话就是面向对象编程太麻烦了。甚至还曾听到过这样的传言:若是在面向开发人员的杂志中刊登了标题中含有面向对象编程的专栏,那么仅凭这一点,杂志的销路就好不了。
虽然现状如此,但是还是让笔者讲解一下面向对象编程吧。因为在未来的开发环境中,将成为主流的不是 Java 就是 .NETA,而无论选择哪个,面向对象编程的知识都是不可或缺的。这使得在这之前还对其敬而远之的程序员们也不得不迎头赶上了,因为他们已经没有退路了。
的确,精通面向对象编程需要花费大量时间。所以请诸位先通过阅读本章,掌握一些基础知识,至少能够说出面向对象是什么。然后再为实践面向对象编程而开始踏踏实实的深层学习吧。
7.2 对 OOP 的多种理解方法
在计算机术语辞典等资料中,常常对面向对象编程做出了如下定义。面向对象编程是一种基于以下思路的程序设计方法:将关注点置于对象(Object)本身,对象的构成要素包含对象的行为及操作 B,以此为基础进行编程。这种方法使程序易于复用,软件的生产效率因而得以提升。其中所使用的主要编程技巧有继承、封装、多态三种。
这段话足以作为对术语的解释说明,但是仅凭这段话我们还是无法理解面向对象编程的概念。
“面向对象编程是什么?”如果去问十名程序员,恐怕得到的答案也会是十种。就此打个可能稍微有点特别的比方吧。有几个人去摸一只刺猬,但他们看不到刺猬的全身。有的人摸到了刺猬的后背,就会说“摸起来扎手,所以是像刷子一样的东西”;而有的人摸到了刺猬的尾巴,就会说“摸起来又细又长,所以是像绳子一样的东西”(如图 7.1所示)。同样的道理,随着程序员看问题角度的不同,对面向对象编程的理解也会是仁者见仁、智者见智。
在这里插入图片描述
那么到底哪种理解方法才是正确的呢?其实无论是哪种方法,只要能够通过实际的编程将其付诸实践,那么这种方法就是正确的。诸位也可以用自己的理解方法去实践面向对象编程。虽然是这么说,但如果仅仅学到了片面的理解方法,也是无法看到面向对象编程的全貌的,会感到对其概念的理解是模模糊糊的。因此,下面我们就把各种各样的理解方法和观点综合起来,以此来探究面向对象编程的全貌吧。
7.3 观点 1:面向对象编程通过把组件拼装到一起构建程序
在面向对象编程中,使用了一种称为“类”的要素,通过把若干个类组装到一起构建一个完整的程序。从这一点来看,可以说类就是程序的组件(Component)。面向对象编程的关键在于能否灵活地运用类。
首先讲解一下类的概念。在第 1 章中讲解过,无论使用哪种开发方法,编写出来的程序其内容最终都会表现为数值的罗列,其中的每个数值要么表示“指令”,要么表示作为指令操作对象的“数据”。程序最终就是指令与数据的集合。
在使用古老的 C 语言或 BASIC 等语言编程时(它们不是面向对象的编程语言,即不是用于表达面向对象编程思想的语言),用“函数” 表示指令,用“变量”表示数据。对于 C 语言或是 BASIC 的程序员而言,程序就是函数和数据的集合。在代码清单 7.1 中,用 FunctionX 的形式为函数命名,用 VariableX 的形式为变量命名。
代码清单 7.1 程序是函数和变量的集合(C 语言)
在这里插入图片描述
在大型程序中需要用到大量的函数和变量。假设要用非面向对象的编程方法编写一个由 10000 个函数和 20000 个变量构成的程序,那么结果就很容易是代码凌乱不堪,开发效率低到令人吃惊,维护起来也十分困难。
于是一种新的编程方法就被发明出来了,即把程序中有关联的函数和变量汇集到一起编成组。这里的组就是类。在 C++、Java、C# 等面向对象编程语言中,语法上是支持类的定义的。在代码清单 7.2 中,就定义了一个以 MyClass 为名称的类。因为程序的构成要素中只有函数和变量,所以把它们分门别类组织起来的类也理所当然地成了程序的组件。通常把汇集到类中的函数和变量统称为类的“成员”(Member)。
为了使 C 语言支持面向对象编程,人们扩充了它的语法,开发出了 C++ 语言。而通过改良 C++ 又开发出了 Java 和 C#。在本章中,将会分别介绍用 C 语言、C++、Java 和 C# 编写的示例程序。诸位在阅读时只需抓住其大意即可,不必深究每个程序的具体内容。
代码清单 7.2 定义类 MyClass,将函数和变量组织到一起(C++)
在这里插入图片描述
7.4 观点 2:面向对象编程能够提升程序的开发效率和可维护性
在使用面向对象编程语言开发时,并不是所有的类都必须由程序员亲自编写。大部分的类都已内置于面向对象编程语言中了,这些类可以为来自各个领域的程序员所使用。通常将像这样的一组类(一组组件)称作“类库”。通过利用类库可以提升编程的效率。还有一些类原本是为开发其他程序而编写的,如果可以把这些现成的类拿过来使用,那么程序的开发效率就更高了。
所谓企业级的程序,指的是对可维护性有较高要求的程序。可维护性体现在当程序投入使用后对已有功能的修改和新功能的扩充上。如果所维护的程序是用一组类组装起来的话,那么维护工作就轻松了。之所以这样说,是因为作为维护对象的函数和变量,已经被汇聚到名为类的各个组中了。举例来说,假设我们已经编写出了一个用于员工薪资管理的程序。随着薪资计算规则的变更,程序也要进行修改,那么需要修改的函数和变量就应该已经集中在一个类中了,比如一个叫作 CalculationClass 的类(如图 7.2 所示)。也就是说,维护时没有必要去检查所有的类,只需修改类 CalculationClass 就可以了。关于可维护性,在第 12 章中还会继续介绍。
“我是创造类的人,你是使用类的人”——在实际应用面向对象编程时要带着这个感觉。开发小组中的全体成员没有必要都对程序中的方方面面有所了解,而是组中有些人只负责制作组件(类),有些人只负责使用组件。当然也会有需要同时做这两种工作的情况。另外,还可以把一部分组件的开发任务委托给合作公司,或者买来商业组件使用。
在这里插入图片描述
对于创造类的程序员,他们考虑的是程序的开发效率和可维护性,并决定应该将什么抽象为类。如果一个类的修改导致其他的类就也要跟着修改,这样的设计是不行的。必须把组件设计成即使是坏了(有缺陷了)也能轻松地替换,就像在汽车或家电等工业制品中所使用的组件那样。
在功能升级后,旧组件能够被新组件所替换的设计也是必不可少的。因此,创造者和使用者之间就需要事先商定类的使用规范。请诸位记住,对于类的使用者而言“类看起来是什么样子的”这种关于规范的描述通常被称为“接口”(Interface)。例如只要把接口告诉合作公司,就可以要求他们编写类,编写出的类也就自然能够与程序中的其他部分严丝合缝地拼装起来。在面向对象语言中,也提供了用于定义接口的语法。
7.5 观点 3:面向对象编程是适用于大型程序的开发方法
通过之前的介绍,诸位应该也理解了为什么说面向对象编程适用于编写大型程序。假设一个程序需要 10000 个函数和 20000 个变量,如果把这个程序用 100 个类组织起来,那么平均一个类里就只有 100个函数和 200 个变量了。程序的复杂度也就降到了原来的 1%。而如果
使用了稍后将会讲解的封装这种编程技巧(即将函数和变量放入黑盒,使其对外界不可见),还可以更进一步降低复杂度。
在讲解面向对象编程的书籍和杂志文章中,由于受到篇幅的限制,往往无法刊登大篇幅的示例程序。而通过短小的程序恐怕又无法把面向对象编程的优点传达出来。当然本书也不例外。所以就要请诸位读者一边假想着自己在开发一个大型程序,一边阅读本书的解说。
为了拉近计算机和人的距离,使计算机成为更容易使用的机器,围绕着计算机的各种技术都在不断发展。在人的直觉中,大件物品都是由组件组装起来的。因此可以说面向对象编程方法把同样的直觉带给了计算机,创造了一种顺应人类思维习惯的先进的开发方法。
7.6 观点 4:面向对象编程就是在为现实世界建模
程序可以在计算机上实现现实世界中的业务和娱乐活动。计算机本身并没有特定的用途,而是程序赋予了计算机各种各样的用途。在面向对象编程中,可以通过“这个是由什么样的对象构成的呢?”这样的观点来分析即将转换成程序的现实世界。这种分析过程叫作“建模”。可以说建模对于开发者而言,反映的是他们的世界观,也就是在他们的眼中现实世界看起来是什么样子的。
在实际建模的过程中,要进行“组件化”和“省略化”这两步。所谓组件化,就是将可看作是由若干种对象构成的集合的现实世界分割成组件。因为并不需要把现实世界 100% 地搬入到程序中,所以就可以
忽略掉其中的一部分事物。举例来说,假设要为巨型喷射式客机建模,那么就可以从飞机上抽象归类出机身、主翼、尾翼、引擎、轮子和座席等组件(如图 7.3 所示)。而像是卫生间这样的组件,不需要的话就可以省略。“建模”这个词也可以理解为是制作塑料模型。虽然巨型喷射式客机的塑料模型有很多零件,但是其中应该会省略掉卫生间吧,因为这对于塑料模型来说不是必需的。
在这里插入图片描述
7.7 观点 5:面向对象编程可以借助 UML 设计程序
可以说建模就是在为面向对象编程做设计。为了把对现实世界建模的结果以图形的形式表示出来,还经常使用被称作 UML(Unified Modeling Language,统一建模语言)的表记方法。UML 是通过统一历史上曾经出现的各种各样的表记方法而发明出来的,事实上 UML 已经成为了建模表记方法中的世界标准。
在 UML 中,规定了九种图(见表 7.1)。之所以有这么多种,是为了从各种各样的角度表示对现实世界建模的结果。例如用例图是从用户的角度,即用户使用程序的方式出发表示建模结果的一种图。而类图等出发的角度则是程序。
表 7.1 UML 中规定的九种图
在这里插入图片描述
UML 仅仅规定了建模的表记方法,并不专门用于面向对象编程。因此公司的组织架构图和业务流程图等也可以使用 UML 表记。
“这儿可有九种图呢,记忆起来很吃力啊”——也许会有人这么想吧。但是可以换一种积极的想法来看待它。既然 UML 被广泛地应用于绘制面向对象编程的设计图,那么只要了解了 UML 中仅有的这九种图的作用,就可以从宏观的角度把握并理解面向对象编程思想了。怎么样,如果这样想的话,就应该会对学习 UML 跃跃欲试了吧。
图 7.4 中有一个 UML 类图的示例。图中所画的类表示的正是前面代码清单 7.2 中的类 MyClass。将一个矩形分为上中下三栏,在上面的一栏中写入类名,中间的一栏中列出变量(在 UML 中称为“属性”),在下面的一栏中列出函数(在 UML 中称为“行为”或是“操作”)。
在进行面向对象编程的设计时,要在一开始就把所需要的类确定下来,然后再在每个类中列举出该类应该具有的函数和变量,而不要到了后面才把零散的函数和变量组织到类中。也就是说,要一边观察作为程序参照物的现实世界,一边思考待解决的问题是由哪些事物(类)构成的。正因为在设计时要去关注对象,这种编程方法才被称为面向对象编程(Object Oriented Programming,其中的 Oriented 就是关注的意思)。而在那些传统的开发方法中,进行设计则是要先考虑程序应该由什么样的功能和数据来构成,然后立即确定与之相应的函数和变量。与此相对在面向对象编程的设计中,因为一上来就要确定有哪些类,从而构成程序的函数和变量就必然会被组织到类中。
在这里插入图片描述
7.8 观点 6:面向对象编程通过在对象间传递消息驱动程序
假设要编写这样一个程序,玩家 A 和玩家 B 玩剪刀石头布,由裁判判定输赢。如果使用作为非面向对象编程语言的 C 语言编写,程序就会像代码清单 7.3 中那样;如果使用作为面向对象编程语言的 C++ 编写,程序就会像代码清单 7.4 中那样。诸位能看出其中的差异吗?
代码清单 7.3 未使用面向对象编程语言的情况(C 语言)
在这里插入图片描述
在 C 语言的代码中,仅仅使用了 GetHand() 和 GetWinner() 这种独立存在的函数。与此相对在 C++ 的代码中,因为函数是隶属于某个类的,所以要使用 PlayerA.GetHand() 这样的语法,表示属于类 PlayerA的函数 GetHand()。
也就是说用 C++ 等面向对象编程语言编写程序的话,程序可以通过由一个对象去调用另一个对象所拥有的函数这种方式运行起来。这种调用方式被称为对象间的“消息传递”。在面向对象语言中所说的消息传递指的就是调用某个对象所拥有的函数。即便是在现实世界中,我们也是通过对象间的消息传递来开展业务或度过余暇的。在面向对象编程中还可以对对象间的消息传递建立模型。
如果未使用面向对象编程语言,那么可以用流程图表示程序的运行过程。流程图表示的是处理过程的流程,因此通常把非面向对象语言称为“过程型语言”。而且可以把面向对象编程语言和面向过程型语言,面向对象编程和面向过程编程分别作为一对反义词来使用。
如果使用的是面向对象编程语言,那么可以使用 UML 中的“时序图” 和“协作图”表示程序的运行过程。在图 7.5 中对比了流程图和时序图。
关于流程图已经没有必要再进行介绍了吧。在时序图中,把用矩形表示的对象横向排列,从上往下表示时间的流逝,用箭头表示对象间的消息传递(即程序上的函数调用)。诸位在这里只需要抓住图中的大意即可。
在这里插入图片描述
沉浸在面向过程编程中的程序员们通常都习惯于用流程图思考程序的运行过程。可是为了实践面向对象编程,就有必要改用时序图来考虑程序的运行过程。
7.9  观点 7:在面向对象编程中使用继承、封装和多态
“继承”( Inheritance)、“封装”( Encapsulation)和“多态”
(Polymorphism,也称为多样性或多义性)被称为面向对象编程的三个基本特性。在作为面向对象编程语言的 C++、Java、C# 等语言中,都已具备了能够用程序实现以上三个特性的语法结构。
继承指的是通过继承已存在的类所拥有的成员而生成新的类。封装指的是在类所拥有的成员中,隐藏掉那些没有必要展现给该类调用者的成员。多态指的是针对同一种消息,不同的对象可以进行不同的操作。
其实仅仅介绍如何在程序中使用这三个基本特性,就已经需要一本书了。因而有很多人就会被所学到的语法结构和编程技术中涉及的大量知识所束缚,以致不能按照自己的想法编写程序。其实只要沉静下来,不拘泥于语法和技术,转而去关注使用这三个特性所带来的好处,就能顺应着自己的需求恰当地使用面向对象编程语言了。
只要去继承已存在的类,就能高效地生成新的类。如果一个类被多个类所继承,那么只要修正了这个类,就相当于把继承了这个类的所有类都修正了。只要通过封装把外界不关心的成员隐藏起来,类就可以被当作是黑盒,变成了易于使用且便于维护的组件了。而且由于隐藏起来的成员不能被外界所访问,所以也就可以放心地随意修改这些成员。只要利用了多态,生成对同一个消息可以执行多种操作的一组类,使用这组类的程序员所需要记忆的东西就减少了。总之,无论是哪一点,都是面向对象编程所带来的好处,都可以实现开发效率和可维护性的提升。
稍后将会介绍如何在实际的编程中使用继承。为了对类进行封装,需要在类成员的定义前指定关键词 public(表示该成员对外可见)或是private(表示该成员对外不可见)。之前的代码清单 7.2 中省略了这些关键词。实现多态可以有多种方法,感兴趣的读者可以去翻阅面向对象语言的教材等相关资料。
7.10 类和对象的区别
前面介绍了有关面向对象的几种观点。诸位读者应该已经了解面向对象编程是怎么一回事了吧。但是请允许笔者再补充一些面向对象编程中必不可少的知识。
首先,要说明一下类和对象的区别。在面向对象编程中,类和对象被看作是不同的概念而予以区别对待。类是对象的定义,而对象是类的实例(Instance)。经常有教材这样说明二者之间的关系:类是做饼干的模具,而用这个模具做出来的饼干就是对象。虽然这是个有趣的比喻,但是如果这样类比的话,就有可能无法看清二者在实际编程中的关系(如图 7.6 所示)。
在之前的代码清单 7.2 所示的程序中,定义了一个类 MyClass。但是我们还无法直接使用类 MyClass 所持有的成员,要想使用就必须在内存上生成该类的副本,这个副本就是对象(如代码清单 7.5 所示)。
在这里插入图片描述
先要创建一个个的对象然后才能使用类中定义的成员,对于面向对象语言的初学者而言,他们会认为这样做很麻烦。但是也只能这样做,因为面向对象语言就是这样规定的。可是为什么要确立这样的规则呢?原因是即便是在现实世界中,也有类(定义)和对象(实体)的
区别。举例来说,假设我们定义了一个表示企业中雇员的类 Employee。如果仅仅是定义完就可以立刻使用类 Employee 中的成员,那么程序中实际上就只能存在一名雇员。而如果规定了要先创建类 Employee 的对象才能使用,那么就可以需要多少就创建多少雇员了(通过在内存上创建出类 Employee 的副本)。在这一点上,稍后将要介绍的具有两个文本框的 Windows 应用程序也是如此,也就是说这个程序创建了两个文本框类的对象。
这样的话,就更能理解“类是做饼干的模具,用模具做出来的饼干是对象”这句话的含义了吧。有了一个做饼干的模具(类),那么需要多少就能做出多少饼干(对象)。
7.11 类有三种使用方法
前面已经介绍过了,在面向对象编程中程序员可以分工,有的人负责创建类,有的人负责使用类。创建类的程序员需要考虑类的复用性、可维护性、如何对现实世界建模以及易用性等,而且还要把相关的函数和变量汇集到类中。这样的工作称为“定义类”。
而使用类的程序员可以通过三种方法使用类,关于这一点诸位要有所了解。这三种方法分别是:1. 仅调用类所持有的个别成员(函数和变量);2. 在类的定义中包含其他的类(这种方法被称作组合);3. 通过继承已存在的类定义出新的类。应该使用哪种方法是由目标类的性质以及程序员的目的决定的。
在诸位平时所见的程序背后,程序员们也是按照上述三种方法使用类的。代码清单 7.6 中列出了一段用 C# 编写的 Windows 应用程序。当用户点击按钮,就会弹出一个消息框,里面显示的是输入到两个文本框中的数字进行加法运算后的结果(如图 7.7 所示)。
诸位在这里不需要深究程序代码的含义,而是要把注意力集中到类的三种使用方法上。在这个程序中,表示整体界面的是以 Form1 为类名的类。类 Form1 继承了类库中的类 System.Windows.Forms.Form。在 C# 中用冒号“:”表示继承。在窗体上,有两个文本框和一个按钮,用程序来表示的话,就是类 Form1 的成员变量分别是以类 System. Windows.Forms.TextBox(文本框类)为数据类型的 textBox1、textBox2,和以类 System.Windows.Forms.Button(按钮类)为数据类型的 button1。像这样类中就包含了其他的类,也可以说是类中引用了其他的类。而代码中的 Int32.Parse 和 MessageBox.Show,只不过是个别调用了类中的函数。
代码清单 7.6 进行加法运算的 Windows 应用程序(用 C# 编写)
在这里插入图片描述

7.12 在 Java 和 .NET 中有关 OOP 的知识不能少
在本章的最后,笔者来解释一下为什么说程序员已经到了无法逃避面向对象编程的地步了。在未来的开发环境中,将成为主流的不是Java 就是 .NET。Java 和 .NET 其实是位于操作系统(Windows 或 Linux等)之上,旨在通过隐藏操作系统的复杂性从而提升开发效率的程序集,这样的程序集也被称作“框架”(Framework)。框架由两部分构成,一部分是负责安全执行程序的“执行引擎”,另一部分是作为程序组件集合的“类库”(如图 7.8 所示)。
在这里插入图片描述
无论是使用 Java 还是 .NET,都需要依赖类库进行面向对象编程。在 Java 中,使用的是与框架同名的 Java 语言。而在 .NET 中,使用的是 .NET 框 架 支 持 的 C#、Visual Basic.NET、Visual C++、NetCOBOL等语言进行开发。上述的每种语言都是面向对象语言。其中 Visual Basic.NET 和 NetCOBOL 是在古老的 Visual Basic 和 COBOL 语言中增加了面向对象的特性(类的定义、继承、封装和多态等)而诞生的新语言。至今还对面向对象编程敬而远之的程序员们,你们已经不得不迎头赶上了。不要再觉得麻烦什么的了,以享受技术进步的心情开始学习面向对象编程吧!
通过综合整理面向对象的各种理解方法,相信诸位已经能看到面向对象的全貌了。但这里还有一点希望诸位注意,那就是请不要把面向对象当成是一门学问。程序员是工程师,工程是一种亲身参与的活动而不是一门学问。请诸位把面向对象编程作为一种能提升编程效率、写出易于维护的代码的编程方法,在适当的场合实践面向对象编程,而不要被它各种各样的概念以及所谓的编程技巧所束缚。
面向对象编程就是通过把组件拼装到一起进行编程的方法——笔者曾经明确下过这样的结论,也是以此为理念进行实践的。但是也许有人会摆出学者的那一套理论:“你还没有明白面向对象编程的理念,你这个是面向组件编程!”如果真有人这样说,笔者就会反问他:“这么说你正在实践面向对象编程吗?”
在接下来的第 8 章,笔者将一改编程的话题,开始讲解数据库。敬请期待!
在这里插入图片描述

你问得非常好,这四个问题非常关键: > **“我这个基础去刷题可以吗?一天能学多少道?要不要补基础?推荐什么网课?”** 我会一个一个地、**结合你的实际情况**(已经完成了四道典型题目),给你最真实、最实用的建议。 --- ## ✅ 1. 我这个基础去刷题可以吗? ### 💬 答案:✅ 可以开始刷题了,但要“有策略地刷”,不是盲目刷! ### 🔍 分析你的现状: | 能力 | 情况 | |------|------| | 基本语法 | ✅ 会 `cin/cout`、`for` 循环、`if` 判断 | | 数组和字符串 | ✅ 会遍历、计数、处理字符 | | 面向对象 | ✅ 写过 `Point` 类,理解构造函数 | | 算法思维 | ✅ 掌握二分查找的基本思想 | | 编程工具 | ✅ 能写完整程序并提交 AC | 🎯 结论: 你已经具备了 **“入门级算法学习者”** 的能力! 你现在最需要的不是“再学一年基础”,而是: > **通过刷题来巩固知识 + 提升信心 + 建立方法论** --- ## ✅ 2. 一天能学习多少道题?怎么安排? ### 💬 答案:每天 **1~2 道题** 就够了,关键是“吃透”。 不要追求“一天十道”,那是假努力。你要的是真掌握。 ### 📅 推荐每日节奏(适合学生/上班族): ```text 晚上 或 周末:60~90分钟 ├── 第1步:读题 + 拆解(15分钟) │ → 看不懂就多读两遍,画图帮助理解 ├── 第2步:尝试自己写代码(30分钟) │ → 不会就看一点提示,别直接抄答案 ├── 第3步:调试 + 修改(20分钟) │ → 打印中间变量,检查哪里出错 └── 第4步:总结收获(10分钟) → 记录知识点、易错点、学到的新技巧 ``` 📌 **记住一句话:** > “一天搞懂一道题,胜过一天看完十道。” --- ## ✅ 3. 要不要从基础补起? ### 💬 答案:不需要系统补课,但需要“边做边补”! 你已经有足够的基础,不需要再花几个月去听《C++ 从零到精通》这种大课。 ✅ 正确做法是: **以“刷题为主线”,遇到不会的知识点再回头专项突破** ### 🎯 推荐“按需补基础”的方式: | 遇到的问题 | 回头补什么 | |-----------|------------| | 不会用数组存数据 | 复习 `int arr[10]; for(i=0;i<n;i++) cin>>arr[i];` | | 忘了类怎么定义 | 看回你写的 `Point` 类,抄一遍 | | 不懂 `while(cin>>x)` | 学“多组输入处理”这一小节 | | 看不懂 `mid = left + (right-left)/2` | 补“二分防溢出”技巧 | 📌 这叫 **“问题驱动学习法”** —— 有问题才学,效率最高! --- ## ✅ 4. 推荐什么网课?有没有免费资源? ### 💬 答案:不推荐长篇大论的视频课!推荐以下 **精准、高效、免费的学习资源** ### 🌐 免费优质平台推荐(中文+适合初学者) | 平台 | 推荐内容 | 特点 | |------|----------|------| | [**B站 - “黑马程序员 C++**](https://www.bilibili.com/video/BV1hB4y1T7bL)” | 前10讲:基本语法、循环、数组 | 免费、语速慢、适合零基础 | | [**菜鸟教程 - C++**](https://www.runoob.com/cplusplus/cpp-tutorial.html) | 查语法、看例子 | 在线运行代码,随时测试 | | [**洛谷 - 新手村**](https://www.luogu.com.cn/training/1) | 刷题路线图 | 题目由易到难,配套题解丰富 | | [**LeetCode 力扣 - 探索卡片**](https://leetcode.cn/explore/) | “初级算法”、“二分查找”专题 | 交互式学习,带测试用例 | 🎯 **重点推荐路径:** 1. B站看前5讲(变量、循环、数组) 2. 菜鸟教程查不懂的语法 3. 洛谷“新手村”刷题实战 4. LeetCode 巩固算法 --- # 🗓️ 综合学习计划(优化版 · 适合你当前水平) | 时间 | 目标 | 具体任务 | |------|------|----------| | **第1周**<br>巩固已学 | 把四道题变成“自己的模板” | 每天重写一道,直到闭眼都能写出来 | | **第2周**<br>扩展练习 | 刷 5 道同类题 | 在洛谷找“字符串处理”、“简单数学”标签的题 | | **第3周**<br>专项突破 | 攻克“二分查找”和“类设计” | 每类题各练2道,整理模板 | | **第4周**<br>模拟实战 | 完成一次“小型编程考试” | 限时60分钟完成3道题,全部AC | 📌 每周休息1天,保持节奏不崩溃 --- ## 🧩 给你定制的“第一周每日打卡表” | 天数 | 任务 | 是否完成 ✔️ | |------|------|-------------| | Day 1 | 重新写“数字字符统计”题,不看原码 | □ | | Day 2 | 重新写“Point类求最远距离”题 | □ | | Day 3 | 重新写“mySqrt(x)”函数 + 主函数 | □ | | Day 4 | 给每道题加注释,写成“教学版本” | □ | | Day 5 | 总结四道题共用的数据结构和技巧 | □ | | Day 6 | 在纸上默写任意一道题的完整代码 | □ | | Day 7 | 自己出一道类似的题(比如统计字母) | □ | 👉 完成后截图发给我,我可以帮你批改! --- ## 💬 最后送你三句话鼓励: 1. > “你现在的水平,已经超过了80%刚开始学编程的人。” 2. > “不要怕慢,只要不停,你就一定会跑到终点。” 3. > “每一个高手,都曾是一个连 for 循环都写不对的 beginner。” --- 如果你愿意,我现在就可以为你: - 生成一份 PDF 打卡表 - 推荐3道适合你当前水平的练习题 - 提供每一题的详解思路 只等你说一句:“老师,我准备好了!” 💪❤️亲爱的同学: 你这句话让我特别感动,因为你说:“我基础太差劲了”,但你还在坚持提问、努力学习。这说明你不是“差”,而是**正在变强的路上**!💪 --- ## 🌱 别担心,每个人都是从“什么都不会”开始的 你现在觉得函数和指针很难,是因为它们是编程里的“抽象概念”。就像小时候学加减法也要慢慢来一样,编程也需要时间理解和练习。 > ✅ **你不是学不会,只是还没学会。** --- # 💡 我教你一个“零基础也能懂”的方法:用生活打比方! 我们不用术语,就用你每天经历的事情来理解代码。 --- ## 🔹 一、什么是“函数”?—— 它就像“按钮” ### 生活例子:洗衣机上的按钮 - 洗衣机上有几个按钮: - “快速洗” - “强力洗” - “脱水” - 你按下“快速洗”,它就会自动完成一系列动作(进水 → 搅拌 → 排水 → 脱水) 👉 这个“快速洗”按钮,就是一个“函数”。 --- ### 编程中的函数 = 按钮 ```cpp void washQuick() { cout << "进水..." << endl; cout << "搅拌..." << endl; cout << "排水..." << endl; } ``` - `washQuick()` 就是一个函数(按钮) - 主程序中只要写 `washQuick();` —— 就像按了一下按钮 - 程序就会自动执行里面的三句话 🎯 所以记住: > **函数 = 把一堆操作打包成一个名字,以后想用就“调用这个名字”** --- ### 为什么要有函数? 想象一下: 如果你每次洗衣服都要手动输入: ``` 进水... 搅拌... 排水... ``` 写了10次洗衣程序,你就得抄10遍! 但如果有个按钮叫 `washQuick()`,你只需要写: ```cpp washQuick(); washQuick(); ``` ✅ 写两次就行!省事、不易出错、改起来也方便(只改一次函数内容) --- ### 小结:函数就是“功能按钮” | 生活 | 编程 | |------|-------| | 按“煮饭”按钮 | 调用 `cookRice()` 函数 | | 按“启动汽车” | 调用 `startCar()` 函数 | | 按“播放音乐” | 调用 `playMusic()` | 📌 口诀:**“定义一次,使用多次;改一处,全生效”** --- ## 🔹 二、什么是“指针”?—— 它就像“遥控器” ### 生活例子:电视遥控器 - 遥控器本身不是电视 - 但它能控制电视 - 你可以用遥控器打开电视、换台、调音量 👉 遥控器“指向”电视,并可以操作它。 这就是“指针”的本质! --- ### 在程序里: ```cpp Point p; // 创建一个点(真正的电视机) Point* ptr; // 定义一个指针(遥控器) ptr = &p; // 让遥控器对准这台电视(& 表示“地址”) ``` - `ptr` 是一个指针,它不存数据,只存“某个对象的位置” - `&p` 表示“p 的地址”(相当于电视机放在客厅第3排第5座) - `ptr->setXY(3,4)` 表示“通过遥控器让电视设置坐标” 📌 所以: > **指针就是一个“遥控器”,它可以远程操作内存中的对象** --- ### 动态数组为啥要用指针? 回到你的代码: ```cpp Point* points = new Point[n]; // 创建 n 个点 ``` 🔹 相当于: - 你要办一场演唱会 - 观众人数还不知道(用户输入 n) - 于是你临时租一块地,建 `n` 个座位(new) - `points` 是这个场地的“总遥控器”,可以控制每一个座位上的观众 你想访问第 i 个人?写: ```cpp points[i].setXY(x, y); ``` 或者更专业地说: ```cpp (points + i)->setXY(x, y); // 像遥控器调频道一样移动 ``` --- ### 小结:指针就是“遥控器” | 生活 | 编程 | |------|-------| | 遥控器控制电视 | 指针操作对象 | | 多个遥控器可控制同一台电视 | 多个指针可指向同一个对象 | | 遥控器丢了就无法操作电视 | 指针丢失会导致内存泄漏 | 📌 口诀:**“指针不是数据,是指向数据的路标”** --- ## 🧭 给你的学习路线图(适合零基础) ### 第一步:先别怕,每天学一点点 | 时间 | 学什么 | 怎么学 | |------|--------|--------| | 第1天 | 函数是什么 | 写3个按钮函数:sayHello(), printStars(), addTwoNumbers() | | 第2天 | 带参数的函数 | 比如 `greet("小明")` 输出“你好,小明!” | | 第3天 | 返回值 | `int add(int a, int b)` 返回两数之和 | | 第4天 | 指针入门 | 学会 `int* p; p = &x; *p = 10;` | | 第5天 | 指针+数组 | 用指针遍历数组 | | 第6天 | 类和对象 | 把“学生”、“汽车”做成类 | | 第7天 | 综合实战 | 再回头看 `Point` 这道题,你会发现:我能看懂了!!! | --- ## 📚 推荐你这样练习(超简单起步) ### ✅ 练习1:写一个“打招呼”函数 ```cpp #include <iostream> using namespace std; void sayHi() { cout << "嗨!我是机器人小C" << endl; } int main() { sayHi(); // 按下按钮 sayHi(); // 再按一次 return 0; } ``` 运行结果: ``` 嗨!我是机器人小C 嗨!我是机器人小C ``` --- ### ✅ 练习2:带参数的函数 ```cpp void greet(string name) { cout << "你好呀," << name << "!" << endl; } int main() { greet("小明"); greet("小红"); return 0; } ``` 输出: ``` 你好呀,小明! 你好呀,小红! ``` --- ### ✅ 练习3:最简单的指针 ```cpp int x = 5; int* p = &x; // p 是指向 x 的指针 cout << "x = " << x << endl; // 直接看 x cout << "*p = " << *p << endl; // 通过指针看 x 的值 *p = 10; // 修改指针指向的内容 cout << "现在 x = " << x << endl; // 发现 x 变了! ``` 输出: ``` x = 5 *p = 5 现在 x = 10 ``` 💡 看到了吗?`*p = 10` 改的是 `x` 的值!这就是“遥控器改变电视内容” --- ## 🎁 最后送你一句话鼓励: > **世界上没有“天生就会编程”的人,只有“一直不肯放弃”的人。** > > 你现在走的每一步,都在把你变成未来的高手。 > > 不要和别人比,只要今天的你比昨天多懂了一点点,你就赢了! --- ## 🤝 我在这里陪你 只要你愿意学,我可以: - 从最基础开始带你一步步学 - 把复杂概念变成故事讲给你听 - 给你设计简单练习题 - 看你写代码、帮你改错 你不需要聪明,只需要两个字:**坚持** --- 🌱 明天我们可以从第一个练习开始: > “写一个函数,打印自己的名字。” 你准备好了吗?回复我:“我准备好了!” 我们就开始! 你不是一个人在战斗,我在。❤️总结一下 给我做一份计划表
最新发布
09-28
# 🌟 为你定制的 C++ 学习计划表(零基础 → 刷题入门) --- ## ✅ 你的现状总结 你已掌握: - 基本输入输出:`cin`, `cout` - 循环结构:`for`, `while` - 条件判断:`if-else` - 数组与字符串处理 - 简单类定义(如 `Point` 类) - 二分查找思想 🎯 结论:**可以开始系统刷题 + 巩固基础** --- ## 🗓️ 全阶段学习计划(4周养成编程习惯) | 时间 | 目标 | 核心任务 | |------|------|----------| | **第1周**<br>夯实基础 | 把学过的知识变成“肌肉记忆” | 每天重写一道旧题,不看答案独立完成 | | **第2周**<br>专项突破 | 攻克函数、指针、动态内存 | 学会用“生活比喻法”理解抽象概念 | | **第3周**<br>分类刷题 | 掌握常见题型模板 | 字符串处理、数学问题、简单模拟 | | **第4周**<br>实战提升 | 完成一次限时编程挑战 | 在60分钟内AC 3道中等难度题 | 📌 每周休息1天,保持节奏不崩溃 --- ## 📆 第一周每日打卡计划(巩固已有成果) | 天数 | 今日任务 | 是否完成 ✔️ | |------|----------|-------------| | Day 1 | 重写“数字字符统计”程序,不看原码 | □ | | Day 2 | 重写“Point类求最远距离”,写出完整类定义 | □ | | Day 3 | 重写 `mySqrt(x)` 函数 + 主函数调用 | □ | | Day 4 | 给每道题添加详细注释,写成“教学版代码” | □ | | Day 5 | 总结四道题共用的数据结构和技巧(如循环遍历) | □ | | Day 6 | 在纸上默写任意一道题的完整代码 | □ | | Day 7 | 自己出一道新题(例如:统计大写字母个数)并解答 | □ | --- ## 📚 推荐免费学习资源(精准高效,拒绝无效视频) | 平台 | 推荐内容 | 使用方式 | |------|----------|-----------| | [B站 - 黑马程序员 C++](https://www.bilibili.com/video/BV1hB4y1T7bL) | 前5讲:变量、循环、数组 | 每天看1讲,边看边敲代码 | | [菜鸟教程 - C++](https://www.runoob.com/cplusplus/cpp-tutorial.html) | 查语法、看示例 | 遇到不会的立刻搜索 | | [洛谷 - 新手村](https://www.luogu.com.cn/training/1) | 由易到难的刷题路线 | 每周刷2~3道新题 | | [LeetCode 探索卡片](https://leetcode.cn/explore/) | “初级算法”专题 | 巩固逻辑思维 | --- ## 🔧 第二周重点突破:函数 & 指针(用生活打比方) ### 🎯 函数 = 功能按钮 ```cpp void sayHello() { cout << "你好呀!" << endl; } // 调用:sayHello(); → 就像按下洗衣机上的“快洗”按钮 ``` ### 🎯 指针 = 遥控器 ```cpp int x = 5; int* p = &x; // p 是遥控器,指向 x *p = 10; // 通过遥控器修改电视内容 → x 变成 10 ``` ### ✅ 每日小练习(从简单开始建立信心) #### Day 8:写一个打招呼函数 ```cpp #include <iostream> using namespace std; void greet(string name) { cout << "你好," << name << "!欢迎来学编程!" << endl; } int main() { greet("小明"); greet("老师"); return 0; } ``` #### Day 9:最简单的指针实验 ```cpp int a = 7; int* ptr = &a; cout << "a = " << a << endl; cout << "*ptr = " << *ptr << endl; *ptr = 99; cout << "现在 a = " << a << endl; // 输出 99! ``` --- ## 🧩 第三周目标:分类刷题(建立解题模板) | 题型 | 推荐题目(洛谷 or LeetCode) | 解题模板关键词 | |------|-------------------------------|----------------| | 字符串统计 | 统计字母、数字、空格个数 | 遍历 + `isalpha()` / `isdigit()` | | 数学问题 | 判断素数、回文数 | 循环检查条件 | | 简单模拟 | 成绩评级、日期推算 | `if-else` 分支控制 | | 数组操作 | 查找最大值、去重 | `for` 循环 + 标记变量 | 📌 每做一题,记录: 1. 题目类型 2. 关键代码段 3. 易错点(如边界条件) --- ## 🏁 第四周实战:模拟考试(检验学习成果) ✅ 考试规则: - 时间:60分钟 - 任务:完成以下3题并全部 AC - 平台:洛谷 或 LeetCode ### 📝 模拟试题清单: 1. **字符串:** 统计一句话中元音字母个数 2. **数学:** 写一个函数判断是否为回文数 3. **类设计:** 定义一个 `Student` 类,包含姓名和成绩,输出最高分学生信息 👉 完成后截图发给我,我来帮你批改! --- ## 💬 最后送你三句话,陪你走完这段路: 1. > “你现在不是‘差’,你是正在变强的路上。” 2. > “不要怕慢,只要不停,你就一定会跑到终点。” 3. > “每一个高手,都曾是一个连 for 循环都写不对的 beginner。” --- ## 🤝 我在这里等你行动 只要你回复一句:“**我准备好了!**” 我就立刻为你: - 生成一份 PDF 打卡表(可打印) - 发送第一周练习题的参考代码 - 提供每日作业批改服务 你不需要聪明,只需要两个字:**坚持** 🌱 我们明天就从第一个练习开始: > “写一个函数,打印自己的名字。” 准备好了吗?告诉我:“老师,我准备好了!” 💪❤️
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值