第1章 C++概述
第1章 C++概述
学习要点:
- 了解程序设计语言的发展历史
- 了解结构化程序设计和面向对象程序设计的概念
- 认识 C++ 语言程序的基本形式
- 掌握 C++ 语言程序开发的步骤
一、程序设计语言的发展历史
1、计算机语言与程序经历了三个发展阶段
①机器语言与程序——第一代计算机语言
任何信息在计算机内部都是采用【颜色编码-BFD1E9】二进制代码表示的,指挥计算机完成一个基本操作的指令(机器指令)也是由二进制代码表示的。每一条机器指令的格式和含义都是计算机硬件设计者规定的,并按照这个规定制造硬件。一个计算机系统全部机器指令的总和称为指令系统,它就是机器语言。
//用机器语言编制的程序为如下形式:
0000 0100 0001 0010
0000 0100 1100 1010
0001 0010 1111 0000
1000 1010 0110 0001
…
/*
每一行都是一条机器指令,代表一个具体操作;即一条机器指令由16位二进制数组成
*/
机器语言程序能直接在计算机上运行,且运行速度快、效率高,但必须由专业人员编写。机器语言程序紧密依赖于硬件,程序的可移植性差。
移植——指在一种计算机系统下编写的程序经过修改可以在另一种计算机系统中运行,并且运行结果是一样的。改动越少,可移植性越好;改动越多,可移植性越差。
②汇编语言与程序——第二代计算机语言
汇编语言是一种符号语言,用一个有意义的英文单词缩写来代替一条机器指令,如用 ADD 表示加法,用 SUB 表示减法。英文单词缩写被称为助记符,每一个助记符代表一条机器指令,所有指令的助记符集合就是汇编语言。
// 用汇编语言编写的程序有如下形式:
MOV AL 12D // 表示将十进制数12送往累加器AL
SUB AL 18D // 表示从累加器AL中减去十进制数18
· · ·
HLT // 表示停止执行程序
汇编语言改善了程序的可读性和可记忆性。但是汇编语言程序不能在计算机中直接运行,必须把它翻译成相应的机器语言程序才能运行。将汇编语言程序翻译成机器语言程序的过程称为汇编。汇编过程是计算机运行汇编程序自动完成的。
※ 机器语言和汇编语言都是面向机器的语言,统称为低级语言。它们受特定计算机指令系统的限制,通用性较差,一般只适用于专业人员。
③高级语言与程序——第三代
高级语言用类似于人类自然语言和数学语言的方式描述问题、编写程序。
//例如,用C++语言编写的程序片段如下:
int a, b, c; //定义变量a、b和c
cin >> a >> b; //输入变量a、b的值
c = a + b; //将变量a、b的值相加,结果赋给变量c
cout << c; //输出变量c的值
用高级语言编写程序时,编程者不需要考虑具体的计算机硬件系统的内部结构,即不需要考虑计算机的指令系统,而只需要告诉计算机“做什么”即可。至于计算机“怎么做”,即用什么机器指令去完成,不需要编程者考虑。
高级语言也无法在计算机中直接运行。若要运行高级语言程序,首先必须将它翻译成机器语言目标程序,这个翻译的过程称为编译,编译是由“编译程序”(也称“编译器”)完成的。然后由“连接程序”将“目标程序”与系统提供的标准函数的库程序连接,生成可执行程序。可执行程序在计算机中运行。“编译程序”和“连接程序”属于计算机系统软件。
高级语言不仅易学易用、通用性强,而且具有良好的可移植性。如果想把高级语言程序移植到另一个计算机系统中,只需对源程序稍加改动甚至不改动,使用目标计算机系统的编译程序将高级语言源程序重新编译即可。不同的计算机系统具有不同的编译程序。
2、从 C 到 C++
①C语言的特点
优点:(1)语言简洁、紧凑、使用方便、灵活。C语言只有32个关键字,程序书写形式自由。 (2)具有丰富的运算符和数据类型。 (3)C语言可以直接访问内存地址,能进行位操作,使其能够胜任开发操作系统的工作。UNIX操作系统90%代码用C语言完成。 (4)生成的目标代码质量高,程序运行效率高。 (5)可移植性好。
也有局限性:(1)C语言数据类型检查机制较弱,这使得程序中的一些错误不能在编译时被发现。 (2)C语言本身几乎没有支持代码重用的语言结构。 (3)当程序达到一定规模时,程序员很难控制程序的复杂性。
②C++的喻义是对C语言进行“增值”
对C语言进行改进和扩充,并引入了类的概念。C++仍然在不断地发展。
二、[概念]结构化程序设计和面向对象程序设计
C++语言的两个组成部分是过程性语言部分和“类”部分。过程性语言部分和C语言没有本质差别。“类”部分是C语言中没有的,是面向对象程序设计的主体。学习C++,首先必须学习其过程性语言部分,然后再学习“类”部分。过程性语言部分采用的是结构化程序设计方法,“类”部分采用的是面向对象程序设计方法,程序设计方法正在从结构化方向向面向对象演变。C语言仅支持结构化程序设计,而C++语言既支持结构化程序设计也支持面向对象程序设计。
1、结构化程序设计方法
结构化程序设计的主要思想是将任务按功能分解并逐步求精。将复杂的大型任务分解成若干模块,每个模块进一步划分为更小的、功能完整的子模块,继续划分直到原子模块,每个原子模块用一个过程或函数完成。一个过程或函数由多条可顺序执行的语句构成。
编程者将数据与过程或函数分开存储。编写程序的主要技巧在于追踪函数的调用及返回过程,追踪在这个过程中数据发生了怎样的变化。结构化程序设计方法能够较好的分解并解决一些复杂任务。
其主要缺点是,程序依赖于数据结构,当数据结构发生变化时,必须对过程或函数进行修改。另外,当开发一个新任务时,适用于旧任务的程序一般不能重复利用,从编程的角度来说需要重复投入,即重新开发程序。
而基于可重用指导思想的面向对象程序设计方法能够较好地解决这一问题。
2、面向对象程序设计方法
面向对象程序设计(Object Oriented Programming,OOP)试图用客观世界中描述事物的方法来描述一个程序要解决的问题。
对象是客观世界中一个实际存在的事物,如一个具体的“人”就是一个对象。将“人”的共同属性抽象出来就可以构成“类”,如“人”类,它具备的静态属性有姓名、年龄、性别、身高和体重等,它同时具备的动态属性有学习、思考、走路、说话和吃饭等,一般将静态属性作为类的数据成员,而将动态属性作为类的执行代码。
类是一个抽象的概念,而对象是类的具体实例,如“人”类的一个对象就是指一个具体的人。
面向对象程序设计的3个主要特性如下所示。
1)封装性——实现信息隐蔽的基础。
封装:将描述对象的数据(静态属性)及对这些数据进行处理的程序代码(动态属性)有机地组成一个整体,同时对数据及代码的访问权限加以限制。
封装可以使对象内部的数据隐藏起来,在类外不能直接访问它们,而只能通过对象的公有执行代码接口来间接访问对象内部的数据。这样既可保护类中的数据成员,也可使编程者只关心该对象可完成的动作,而不必去关心其内部的数据及代码实现细节。
2)继承性——软件重用的基础。
通过继承可以在已有类的基础之上扩充并产生一个新类。已有类称为基类或父类,新类称为派生类或子类。
派生类除了继承基类的数据及代码之外,可以按需要增加数据和代码。基类的数据和代码在派生类中是可以直接使用的,即基类的代码可以在派生类中重复利用,这就是软件重用,可以提高代码的编写效率。
3)多态性——提高编程效率及提高编程灵活性的机制。
多态分为静态多态和动态多态。
静态多态:分为函数重载、运算符重载、函数模板和类模板。
函数重载:指同名函数完成不同功能,一般用于完成类似功能,如用两个同名函数ads(),分别可以用来求整型量和实型量的绝对值。如果没有函数重载机制,求整型量和实型量的绝对值就必须用两个不同的函数名来实现。函数重载减轻了编程时记忆多个完成类似功能的函数名的负担。
运算符重载:将C++提供的基本运算符运用到新类的机制。例如,加号(+)运算符可以实现C++的基本数据类型的整型量、实型量的相加等。对于用户新定义的类如“复数”类,通过运算符重载机制,可以使用加号实现两个复数对象的直接相加。
函数模板:将结构相同而仅仅数据类型不同的多个函数进行数据类型虚拟化得到的函数的抽象描述。
类模板:将结构相同而仅仅数据类型不同的多个类进行数据类型虚拟化得到的类的抽象描述。在调用函数模板和使用类模板定义对象时,编译器能够根据实际的数据类型以函数模板和类模板为基础自动生成含有具体类型的函数和类,以提高编程效率。
动态多态:是指不同的对象在接收到相同的消息后,以不同的行为去应对。
消息是指对象接收到的需要执行某个“操作”的命令,操作是函数完成的。
动态多态的实现机制是,在基类中定义完成某个操作的虚函数,在不同的派生类中重新定义完成这个“操作”的同名函数,不同派生类中的这些函数完成不同的工作,那么不同派生类对象接收到同样的“消息”时,就可以表现出不同的行为。
例如,基类是一个抽象的“几何图形”,它具有“绘图”行为,但这个行为没有具体含义,因为并不知道具体绘制什么图形。从“几何图形”类派生出“三角形”类、“圆”类或“矩形”类,在派生类中“绘图”功能有具体含义,可重新定义“绘图”功能,实现具体图形的绘制。在基类中的虚拟共同行为“绘图”,在派生类中具有不同的实现行为。不同的派生类对象接收到“绘图”消息时,即产生了不同的行为。
动态多态既提供了“消息”的统一入口,又实现了不同对象对同一消息的不同响应,提高了编程的灵活性。
三、C++语言程序的基本形式
//例1.1 一个简单的C++程序
/* ------------------------------------------------------------------
Li0101.cpp 该程序用于求一个数的平方
------------------------------------------------------------------
*/
#include <iostream>
using namespace std;
int main(void)
{
int num, square; // 定义整型变量 num和square
cout << "num="; // 输出提示信息num=
cin >> num; // 输入一个数,赋给变量 num
square = num * num; // 计算 num 的平方,结果赋值给变量 square
cout << "num的平方为:" << square << '\n'; // 输出变量square的值,
return 0; // '\n'表示换行
}
1、注释语句
注释是对程序功能、算法思路、语句的作用等所做的说明。
两种形式,:①“/*”+“*/”可以跨多行书写;②“//”单行书写
2、编译预处理命令
在程序中如果需要使用系统预先定义的标准函数、符号或对象,在程序的头部均要包含相应的头文件。
在例程中包含头文件iostream,是因为在函数中使用了系统预先定义的、与数据输入输出有关的流对象cin和cout。
3、主函数 main()
一个C++程序必须包含一个主函数main(),是程序流程的主控函数,程序从主函数开始执行。函数体用花括号({})括起来。在函数体中,按照算法写出语句,完成功能。
例程中,main()前面的int表示该函数的返回值是int类型的数据,void表示函数无参数。
例1.2由两个函数组成。程序从主函数main()开始,当执行到C行时发生函数调用,将实际参数(实参)a和b的值分别赋给形式参数(形参)x和y;流程转入A行执行函数sum(),函数sum()执行结束到达B行,通过return语句将计算结果z的值代回主函数,同时程序的执行流程也返回到主函数中的C行,并将计算结果赋值给变量c,继续执行,输出变量c的值。
//例1.2 一个由两个函数构成的C++程序
#include <iostream>
using namespace std;
int sum(int x, int y) // A
{
int z;
z = x + y;
return z; // B
}
int main(void)
{
int a, b, c; // 定义变量a、b和c
a = 3; b = 5; // 给变量a和b赋值
c = sum(a, b); // C行,调用函数sum( ) 求a与b之和,结果赋给变量c
cout << c << '\n'; // 输出c
return 0;
}
从例1.1和例1.2可以看出:
1)C++程序的构成为一个主函数和若干自定义函数。
2)一个函数由两部分组成,①函数首部说明:包括函数的返回值类型、函数名和函数的形参列表。②函数体部分:用花括号({})括起来,在函数体中书写变量定义语句和其他可执行语句。
3)无论main()位置如何,程序总是从main()开始执行,也在main()函数中结束执行。当发生函数的调用及返回时,程序的执行流程在函数间跳转。一个程序中的main()函数是唯一的,其他函数可以有很多个。
4)一般一行书写一条语句,也可以在一行中书写多条语句,或者一条语句书写在多行中。
5)每条语句的结束符是分号(;)。
6)可以用“/*……*/”或“//”对程序的任何部分进行注释。
四、C++语言程序的开发步骤
目前,大多数的程序设计语言都提供了集成开发环境,编程者首先在集成开发环境中输入源程序。
C++源程序的扩展名为.cpp,如源程序名为Li0102.cpp的目标程序文件名为Li0102.obj,其主文件名与源程序主文件名一致,扩展文件名为.obj。最后启动连接程序将目标程序与库程序(一般扩展名为.lib)连接生成可执行程序(一般扩展名为.exe)。计算机直接运行可执行程序。
在程序开发的各个阶段,如编译、连接、执行,均有可能出现错误,当出现错误后,必须返回到编辑状态对源程序进行修改。