一些题外话
学习新东西还是应该及时总结,不然很快就忘记了。而且在总结的过程中,我们会整理自己的语言和思维,对于个人的表达能力也有一定的提高。坚持把简单的事情做好就是不简单,加油吧少女~
我自学c++是从七月份开始的,那时参加一个与数字图像处理、机器学习有关的比赛,很多优秀的代码都是用c++写的,但是我看不懂,也就无从改进了。比赛结果惨不忍睹。所以下定决心要学一下这门神奇、高效的编程语言啦~ 另一方面也为毕业找工作做些准备,毕竟面向对象的编程思想是一种很棒的程序设计技术,系统地学习一下这种思想,以后在其他编程语言(如MATLAB,Python)中也能有意识地用它来解决实际问题。
目前看完了Larry Ullman ,Andreas Signer的《写给大家看的c++书》,看了一部分管皓和安志勇的《c++不再难学——随老鸟快速通关》。看这两个书名就知道是为零基础的人量身打造的入门读物。不过入门真的很重要!!!一开始不需要纠结于一些细节,而应该把精力放在理解编程思想上。当然啦,基本的动手能力还是必须的,所以别偷懒,编程能力是练出来的~
下面总结一下最近学到的新东西以备以后查阅。
正文
1准备工作
在编程过程中,我们可能会遇到很多问题,当自己没有能力解决时往往会想到求助于一些搜索引擎或技术论坛,如何有效地提问也是一门艺术呢。详见Eric Steven Raymond编写的“How to Ask Questions the Smart Way” (http://catb.org/~esr/faqs/smart-questions.html)。
用c++编写程序一般需要多个步骤:明确这个程序的用途和需求-->编程-->编译、链接-->(调试,调试,调试。。。)-->编译、链接-->运行。选择一种适合自己的集成开发环境IDE能够大大提高编程的效率,我用的是Dev-C++。
2数据类型、基本语法、控制结构
常见的数据类型有整数、实数、数组、字符、字符串、指针、结构、联合;
c++对程序的语法要求比较严格,缺少一个小小的分号、括号不对称都会报错,所以一定要养成良好的编程习惯,尽量避免犯一些低级的错误;
在用变量、函数之前一定要先声明或定义;
变量的类型、作用域要认真考虑,在完成基本功能的前提下,尽可能优化代码;
控制结构包括条件if(-else)、三元操作符(?:)、多条件(switch)、循环(while,for);
3输入、输出和文件
每个程序的本质是处理数据,而很多数据需要用户输入或从文件中读取,处理完之后需要把结果展示出来,需要将其输出到交互界面或保存成文件。
一定要检查输入数据的合法性;需要用户多次输入数据时,记得删除缓冲区的残留;
读写文件时一定要检查文件是否真正打开了;
4定义个人函数
创建带输入参数的函数 传递给函数的值必须有正确的类型和顺序;定义函数时必须把所有的必选参数放在可选参数之前;
内联函数 不需要先为它定义一个原型,整个函数都在main函数之前定义;
函数的重载是用同样的名字再定义一个有着不同参数(可以是数据类型不同,也可以是参数个数不同)但是有相同用处的函数;
函数调用时有按值传递、按地址传递、按引用传递这几种;
5对象和类
(例程1
#include
#include
//基类
class Pet{
public:
Pet(std::string theName);
~Pet();
virtual void eat();
virtual void sleep();
virtual void play()=0;//虚方法 //=0抽象方法 如果一个类中有一个抽象方法,那么必须至少还有一个普通的虚方法
static int getCount(); //静态方法
//void setName(std::string theName);
protected://允许这个类和他的子类来访问以下属性和方法
std::string name;
friend class PetRenamer;//友元关系声明 (应该在没有其他办法时才使用友元关系,友元关系太多往往表示设计方案有缺陷)
private:
static int count; //静态属性
};
Pet::Pet(std::string theName){
name=theName;
count++;
std::cout<<"Creating a pet named '"eat();
cat->play();
std::cout<<"\n";
dog->sleep();
dog->eat();
dog->play();
delete cat;
delete dog;
return 0;
}
)
初级
使用对象编程是c++的核心。我们可以把对象理解为一种新的数据类型,不同的是它不仅包括变量(属性)还包括函数(方法)。
在类的声明里,属性和方法前面通常需要加上public、protected、private这三个保留字之一来控制其可访问性;
方法可以互相调用;
构造器和析构器是一类特殊的方法;
this指针;
中级
类的继承机制:该机制是程序员可以创建一个类的层次结构,每个子类均将继承在它的基类里定义的方法和属性。也就是说,可以通过继承机制来对现有的可信的代码进行扩展,大大提高开发效率。
注意继承机制中使用构造器和析构器的语法;
覆盖方法 在某些场合需要在基类里提供一个通用的函数,但在它的子类里需要改变这个方法的实现;
重载方法 与函数的重载相同;
友元关系 一个完全无关的类需要访问某个protected成员或是private成员;类的友元是它自己挑选的,在类的声明里说明;不要滥用友元关系
高级
静态属性和静态方法 不是属于单个对象的而是属于整个类的属性和方法 好处:仍可以通过保留字来控制其访问权限;可以在没有创建任何对象的情况下访问该成员;使某些数据在该类的所有对象之间共享; 不能在静态方法里访问非静态属性;使用静态属性时不要忘记为其分配内存(即在类声明的外部对静态属性做出声明);
虚方法 在子类里对某一方法进行重载,但是通过new方法生成子类对象时用指向基类的指针,再调用该方法时仍是调用的基类里的方法,看例程比较容易理解 在基类里把所有的方法都声明为虚方法会让最终生成的可执行代码的速度变慢,但是可以确保程序的行为符合预期。在实现一个多层次的类继承关系的时候,最顶级的基类应该只有虚方法。
抽象方法 告诉编译器这个方法不可缺少,但是我现在(在这个基类里)还不能为它提供一个实现;要想使用抽象方法就必须在基类里实现它;还有一个细节要注意:如果一个类里要用抽象方法,那么它必须至少还有一个普通的虚方法才行;
多态 能够对多种不同的数据类型进行处理的函数
重载操作符 目的是为了让代码更容易阅读和理解,尽量不要让其失去原始的意义;声明在main函数之前,实现在main函数之后;
多继承 一个子类继承两个或多个基类;
虚继承 告诉编译器从当前这个类派生出来的子类只能拥有那个基类的一个实例
6动态内存管理
动态内存支持程序员创建和使用种种能够根据具体需要扩大或缩小的数据结构;另一个用途是让函数返回一个指向内存块的指针(工厂函数);
动态内存由一些只有地址没有名字的内存块组成,所以要使用指针来访问;虽然动态分配的内存块没有作用域,但用来保存其地址的指针变量都有作用域。
动态内存的申请和释放;delete语句只释放指针所指向的内存块,但是指针仍在;
在动态地创建和使用对象时不要忘记把方法声明为虚方法;
副本构造器和赋值操作符 应用场合-->两个对象进行复制操作,但其中包含指针类型的成员,逐位复制将存在指针隐患。只要声明了一个有指针属性并且将在析构器里释放那块内存的类,就需要实现一个副本构造器和赋值操作符;一定要保证副本构造器对所有的属性都进行了复制。 静态对象强制类型转换/动态对象强制类型转换 与对象打交道时最好总是使用dynamic_cast操作符,记得在继续前进之前检查结果是不是NULL
7命名空间和模块化
头文件 分为系统头文件和自定义头文件 用来保存函数声明、用户自定义的数据类型(结构和类)、模板、全局性常量;只包含最必要的代码即可 ;导入时尽量避免使用绝对路径,因为这会降低代码的可移植性;
实现文件 对于使用者来说看头文件就可以了解函数等的基本用法,对于编译器来说需要清除地直到每个函数或类是怎样实现的;实现文件的名字应该与头文件保持一致;
C预处理器 是人们为了开发C应用程序和加快它们的执行而创建出来的一种工具。
命名空间 由用户自己定义的范围 同一个命名空间里的东西只要在这个命名空间里是独一无二的即可;可以使用namespace关键字在同一个或另一个文件里向一个命名空间里添加新东西;使用命名空间 using thing(用什么写什么,不要只写命名空间的名称,虽然这样也不是不可以),using指令或声明的出现位置决定着从命名空间里提取出来的东西能在哪个作用域内使用;
链接、作用域和储存类 这三个概念是相互关联的,只是观察和描述问题的角度不同~ 当同时编译多个文件时,每个文件都被称为一个翻译单元,在每一个翻译单元里定义的东西能不能及如何在另一个翻译单元里使用是链接发挥作用的地方;分为外链接(每个翻译单元只要知道有该变量存在就可以访问)、内链接(在某个翻译单元里定义的东西只能在该翻译单元里使用)和无连接(在函数里定义的变量只存在于该函数的内部)。每一个变量都有一个储存类,它决定着程序将把变量的值存到计算机上的什么地方、如何储存,以及变量应该有怎样的作用域。
8模板
c++程序设计范型:过程式范型(把程序划分为不同的函数)、面向对象范型(把代码和数据组织成各种各样的类并建立类之间的继承关系)、泛型编程(支持程序员创建函数和类的模板,而不是具体的函数和类,可以用一个解决方案解决多个问题~)
编写和使用自己的泛型代码 函数模板(不要把函数模板分成原型和实现两部分);类模板 (同上);使用内联记号法避免编译器找不到实现,还能使程序的可读性更高;
标准模板库STL
容器和算法 容器是指能容纳两个或多个值的数值结构,不同的问题适合用不同的容器 可以自己写,也可以调用C++标准模板库(STL),那里有很多经过精心的设计和测试的现成的容器;找到了最适用的容器只是编程工作的一部分,还需要一些函数(算法)来处理那个容器里的数据,STL中还提供很多构思巧妙并经过严格测试的算法来解决各种常见问题。STL中常用算法的详细资料可以在网上搜到。
以上就是第一本参考书里讲过的大部分内容,掌握了这些基本的概念就可以编写简单的C++应用程序了。但是很多细节在没有自己动手之前是注意不到的,还是要多动手呀~