前言
学习的基本过程有理解→总结→应用这几个步骤.总结的目的大概是概括出大体的一种思路,一些必然和必不然,整理出"概念",并以概念指导应用.
引入
尝试做一些和编程有关的概念总结.为了满足那个很朴素的想法:总结出概念,编程的思路就水到渠成地来了.---就好像学了单词就想写出好作文一样,当然谁都知道除非天赋惊人,否则这个过程是很困难的.不管怎么说做一点努力.当中肯定有不严谨的地方,看官不必较真
接续
前面谈到了几点:程序包含了函数和数据.函数是程序的基本单元.
类
什么是类?类是面向对象的概念.
类可以看作函数的"变种".本质上还是函数.
推导:不管是静态函数还是成员函数,类只有在调用函数才有意义,比如我们吃饭用筷子并且只用筷子,而筷子除了用来吃饭不作其他用途,那么筷子和"吃饭工具"可以完全对等起来.所以把类看作函数也是没问题的.和面向过程的不同之处是定义函数前先定义类,调用时首先生成对象,再调用函数.
从函数到对象
举个例子:从函数转到类.
现在有个需求:编写一个函数,计算某个地区的气温,已知气温和经纬度,月份有关.
-----函数表达如下: ------注:longtitude:经度; latitude:纬度; (网络搜索)
double getTemprature(double longitude,double latitude,int month);
比如:重庆的经纬度范围是东经105°11′至110°11′、北纬28°10′至32°13′之间,调用时传入即可.
getTemprature(105.11,28.10,6); //调用函数计算气温
-----现在用类表示:
class City{
private:
double longitude;
double latitude;
public:
city(double longt,double lati):longitude(longt),latitude(lati){}
double getTemprature(int month);
}
这里创建了一个名为"City"的类,把经纬度作为属性,气温计算作为函数.
计算气温时,先"使用"类创建对象cq,然后调用成员函数getTemprature();
City cq(105.11,28.10); //创建名为cq的对象,传入经纬度
cq.getTemprature(6); //计算6月份的气温
所以最简单的一种理解:把函数的一部分形参从函数中"抽取"出来,用作一个"类"的"属性".就完成了从单个函数到面向对象的转变,而新做的事仅仅是给"类"加上一个名称.
当建立了"城市"类以后,还可以建立其他和"城市"相关的函数
----同样道理,我们也可以把"月份"抽取出来,建立另一个类
class Month{
private:
int number;
public:
Month(int num):number(num){};
double getTemprature(City& city);
}
计算气温时,先"使用"类创建对象June,然后调用成员函数getTemprature();
City cq(105.11,28.16); //创建名为cq的对象,传入经纬度
Month June(6); //创建名为June的对象,传入6
June.getTemprature(cq); //调用对象方法计算6月份的气温
----注:类名中单词首字母一般大写, 对象一般首个单词首字母小写,这里遵循月份的书写规则.
再发散一下思维,这两个类有什么不同?City类侧重于"经纬度",如你可以传其他城市如武汉的经纬度建立一个名为"wh"的对象,再计算各月的气温.除了计算气温,其他和经纬度有关的函数,比如计算降雨量,顺理成章的就写进这个类里.
Month类侧重于"月份",你可以建立表示其他月份的对象,计算该月里所有城市的气温.同样,和月份有关的函数,也写进这个类里.比如你每个月要准备一次旅行的内容
类的设计看程序员站在什么角度,也可以看出"类"可以看作代码管理的一种手段.
再有初学的时候会有一点迷惑:类里面有函数,函数里面可以有对象(有点像你中有我,我中有你),这是类灵活使用的表现.比如上面的例子Month类的成员函数可以如下书写:因为归根结底他们表达的意思是一致的,所以直接调用已定义好的函数即可,不需重新编写.
class Month{
private:
int number;
public:
Month(int num):number(num){};
double getTemprature(City& city){ //增加部分内容
city.getTemprature(this->number); //this表示指向当前调用对象的指针
};
}
==================了解内容================================================
题外话一:属性不是必须的
#include<iostream>
class tmp {
public:
void show() const {
std::cout << "eat" << std::endl;
}
};
int main() {
tmp a;
a.show();
}
这个例子没有意义.看一下就好
类不给属性,不给构造函数,不会报错(如果定义了属性,必须要有构造函数).从另一个角度说明类本质上是函数
==================了解内容================================================
题外话二:
类中可以"包含"其他对象.类的函数可以调用其他对象的函数,像设计模式中的"行为模式",在这里就不展开了.此外类还有继承,包含,接口,虚方法的多种用法,笔者以前写过,也不展开了.
类的分类
一切都以简单入手,类分为"只有数据","只有方法","有数据也有方法"这几类. 数据援引上一篇帖子里的概念:硬数据和软数据.类本质上是一种代码组织方式,就类似于搭积木一样的,那一块块小积木(函数)才是根本.至于如何搭建,看程序员的设计.
===================================内容分割线==============================
有句话说的是:读万卷书,不如行万里路;行万里路,不如名师指路,名师指路不如自己去悟.
名师的书写得很好,但概念和思维都是别人的,想变成自己的,知其形再知其神,这个过程还是有难度的.自悟开心的地方就是成就感稍强.
重申:以下内容仅属于个人观点.
===================================内容分割线==============================
概念:编程思想和实现
这两篇帖子都在试图用"概念"来描述程序.在谈文件之前,先说说笔者理解的编程思想和实现.
实现
经常在书中看到:这里给出了实现.既然是编程领域里的实现,那就是函数代码了.
实现指的是抽象具体化. 代码是实现的结果.实现的源头是什么呢?编程思想.
编程思想
经常听一句话:编程思想是最重要的.什么是编程思想?
他是一种系统策划,为实现需要定义功能,进行的概念设计.思想比概念更抽象.
举个例子:你想设计一辆汽车,思路是怎样的呢?汽车要有动力,所以有发动机系统;要能调速,需要变速箱系统;要能制动,需要刹车系统;要能转向,需要方向盘系统;需要车厢内有一定美感,需要内饰系统;要能前进后退,需要轮胎;等等
有了初步设计,各个系统之间怎样联系,如何协作,也是需要考虑的.落实到具体设计中,可能还需要考虑更多问题.比如发动机需要散热,需要润滑,则进行相应的设计.
编程思想,实现和概念之间的关系
编程思想可以用文字或者图表来描述,用代码实现.实现过程中会出现"概念".
举个例子:在C++中,vector是动态数组的实现.
思路是:创建一个数组,可以增加和删除元素,并且在增减元素时改变数组的长度.
代码是#include<vector>中的函数.
概念:"动态数组"这个概念随代码而产生.
---- 一般说来,编程思想先于代码和概念存在,前提是"思路"是正确的.但在思考阶段,我想世界上再伟大的科学家也没法保证一次性得到的思路就是完美无缺的.所以"思想"和"概念"是一种相辅相成的关系.如果发现预设逻辑不严谨或者有其他更好的思路,及时从现有代码修正.这也是软件(应用软件和编程语言)不断迭代升级的原因:
编程思想更广阔的应用
所有的软件设计,都可以遵循这个模式:思路→代码→概念.
编程语言本身也是一种实现,他实际上是一种符号系统,语言使用了编译器提供的api,制定了一套编写规则,产生了数组,指针,函数等概念.基于某种编程语言的应用程序,按照编写规则写出代码,经编译后向CPU发出指令.
范围再放大一点,操作系统,硬件设计,其他所有和设计相关的行业,都以思想为出发点.
话再说回来,如果只是调用api,那思想和概念与程序员无关,唯一要做的事情是读懂"代码"的说明.而这对于大多数的"搬砖"程序员也够用了.这里没有厚此薄彼的意思,如果想在编程领域走得更远,就需要深入.
文件
从"物理"的角度看文件,他是一个单元.每个文件由若干个函数组成.所以他本质上和类相同,是代码(函数)的组织方式.简单理解把文件,翻译单元,软件包,软件框架看作同一种事物,统称文件
文件和类的关系
类通常放在文件中,当文件a用#include包含其他文件b,则可以访问被包含文件b中的类.
文件和程序的关系
程序可能包含多个文件.文件相当于"组件"或者"模块".有一些文件里包含的函数是对所有程序都适用的.他们称为"通用文件".比如上面的vector,.只要包含了#include<vector>这个头文件,就可以使用"动态数组"这种数据结构,去建立某种类型的数据集合."通用文件"开发,在C++中,他是用模板来实现的.模板内容笔者后面会试着做一做.
文件的意义
1. 前面说了文件是单独的逻辑单元,简单分为通用和专用.现在可以更新一下认知:
程序:需求→"函数" 满足需求→"调用函数" //先前使用模型
程序: 需求→"文件" 满足需求→"使用文件" //现在使用模型
文件是为了满足功能而存在的.
举个例子:C++中的输入输出流的文件#include<iostream>,他实现了什么功能?
cout<<"Hello World"<<endl;
源码被封装看不见.但他实现功能是调用字库(字库是一个点的集合),把这个集合写入显示窗口的某个位置(笔者的看法,略过),然后被看见.
2.文件可以很好地分工协作.
假设现在你想开发一个MS Word那样的文档处理软件.首先得确定功能模块,界面要有吧,字库要有吧,搜索要有吧,不是单机用的话,网络功能要有吧,想打印的话,驱动要有吧.当然这是架构师干的事(大软件可能有多个架构师),每个架构师在其工作范围内确认文件的功能,并且对文件组织和划分,然后再编写代码---这个例子属于本人想象,并非人人都是架构师.
小结
这两篇帖子像管中窥豹,再从每个管中看到的图像硬拼整个豹子的整个图像一样去总结编程,显得有些窘迫.学习就是单调,枯燥,效果还得看个人资质.
理清程序的步骤:从设计思想→文件→函数,以及通用文件表达出的概念.