1.1 C++简介
1983年,贝尔实验室(Bell Labs)的Bjarne Stroustrup发明了C++。 C++在C语言的基础上进行了扩充和完善,是一种面向对象程序设计(OOP)语言。
Stroustrup说:“这个名字象征着源自于C语言变化的自然演进”。还处于发展完善阶段时被称为“new C”,之后被称为“C with Class”。C++被视为C语言的上层结构,1983年Rick Mascitti建议使用C++这个名字,就是源于C语言中的“++”操作符(变量自增)。而且在共同的命名约定中,使用“+”以表示增强的程序。
支持面向对象编程、泛型编程和过程化编程。
编程领域广泛:常用于系统开发,引擎开发等应用领域,是最受广大程序员喜爱的编程语言之一。
“C with Class”阶段,C语言基础上的特征主要有:类及派生类、共有和私有成员、构造函数和析构函数、友元、内联函数、赋值运算符的重载,等等。
1985年1.0版新增加:虚函数的概念、函数和运算符的重载、引用、常量,等等。
1989年2.0版新增加:类的保护成员、多重继承、对象的初始化与赋值的递归机制、抽象类、静态成员函数、const成员函数,等等。
1993年3.0版本新增加:模板(template),解决了多重继承产生的二义性及其构造/析构函数的处理问题,等等。
1998年C++语言及库标准化:名字空间、标准模板库(STL)、通用算法类和字符串类型,等等。该标准通常简称ANSI C++或ISO C++ 98标准,此后每5年更新一次标准。
2003年通过了C++标准第二版(ISO/IEC 14882:2003)C++03:这个新版本是一次技术性修订,对第一版进行了整理—修订错误、减少多义性等,但没有改变语言特性。
国际标准化组织于2011年9月1日出版发布《ISO/IEC 14882:2011》简称ISO C++ 11标准,取代现行的C++标准、C++98和C++03。
1.2 C++新增特性
更为严格的类型检查
新增变量引用
支持面向对象
- 类和对象、继承、多态、虚函数及RTTI(运行时类型识别)
新增泛型编程
- 支持模板(template),标准模板库(STL)
支持异常处理
支持函数及运算符重载
支持名字空间
1.3 OOP简介
面向对象编程(OOP)
OOP是程序设计工程化的一种方法,软件架构的一种思想。
OOP基本原则是程序是由单个能够起到子程序作用的单元或对象组合而成,以达到软件工程的三个主要目标:重用性、灵活性和扩展性。
- 重用性
代码被重复使用,以减少代码量,就是重用性的重要指标。
- 灵活性
软件系统由很多可以复用的构件随意重构,以达到实现不同的功能,非常灵活。
- 扩展性
软件系统可以容易地新增需求,基本构件也可以轻松的扩展功能。
面向过程设计
对象 = 数据结构 + 算法
程序 = (对象 + 对象 + …)+ 对象间通讯机制
面向对象编程主要涉及概念
类、对象、数据抽象、继承、动态绑定、数据封装、多态性、消息传递。
- 对象(Object)
可以对其做事情的一些东西。一个对象有状态、行为和标识三种属性。
- 类(class)
共享相同属性和方法的对象集合。描述了一类事物的抽象特点,类的方法和属性被称为“成员”。
- 封装(encapsulation)
将数据(数据)和方法(操作)捆绑在一起,创造出一个新的类型的过程。
将接口与实现分离的过程。
- 继承(inherit)
一个类共享了一个或多个其他类定义的属性和方法,在这种关系中子类可以对基类进行扩展、覆盖、重定义。
- 组合
既是类之间的关系也是对象之间的关系。在这种关系中一个对象或者类包含了其他的对象和类。组合描述了“有”关系。
- 多态(polymorphism)
类型理论中的一个概念,一个名称可以表示很多不同类的对象,这些类和一个共同超类有关。因此,这个名称表示的任何对象可以以不同的方式响应一些共同的操作集合。
- 动态绑定(动态联编)
也称动态类型,指的是一个对象或者表达式的类型直到运行时才确定。通常由编译器插入特殊代码来实现。与之对立的是静态类型。
- 静态绑定(静态联编)
也称静态类型,指的是一个对象或者表达式的类型在编译时确定。
- 消息传递
指的是一个对象调用了另一个对象的方法(或者称为成员函数)。
- 方法
也称为成员函数,是指对象上的操作,作为类声明的一部分来定义。方法定义了可以对一个对象执行那些操作。
1.4泛型编程简介
泛型编程由Alexander Stepanov、Meng Lee和David R Musser在惠普实验室工作时所发明,目的是为了实现C++的STL(Standard Template Library 标准模板库)。
C++中的支持机制就是模板(Templates)。模板的实质就是参数化类型,简而言之:把特定的类型信息抽象化,抽象成模板参数T。这样就可以编写出任意类型动作一致的类或方法,在使用时才指定实际类型。
泛型一定程度上杜绝了类型转换。
STL(Standard Template Library)的六大组件:
容器(containers)
迭代器(iterators)
算法(algorithms)
空间配置器(allocator)
配接器(adapters)
仿函数(functors)
图1
泛型容器(containers)
特殊的数据结构,实现了数组、链表、队列、等等,实质是模板类
迭代器(iterators)
一种复杂的指针,可以通过其读写容器中的对象,实质是运算符重载
算法(algorithms)
读写容器对象的逻辑算法:排序、遍历、查找、等等,实质是模板函数
空间配置器(allocator)
容器的空间配置管理的模板类
配接器(adapters)
用来修饰容器、仿函数、迭代器接口
仿函数(functors)
类似函数,通过重载()运算符来模拟函数行为的类
组件间的关系
container(容器) 通过 allocator(配置器) 取得数据储存空间,algorithm(算法)通过 iterator(迭代器)存取 container(容器) 内容,functor(仿函数) 可以协助 algorithm(算法) 完成不同的策略变化,adapter(配接器) 可以修饰或套接 functor(仿函数)。
1.5编译C++程序
C和C++的编程步骤是一致
编辑源码
编译过程
预处理
编译
汇编
链接
图2
C++程序的基本结构:
引用头文件:预处理指令#include
注释://
入口函数:main
编译指令:using namespace
函数体:{ }
C/C++编译器众多,linux平台以gnu C++为主,windows平台以VS为主。
IDE(Integrated Development Environment)环境也很多,譬如Qt的IDE QtCreator的编译器,windows系统是Mingw32、Linux系统下是g++。
表 1
1.6 C和C++兼容及差异
C++融合了三种编程方式:C语法的面向过程编程、C++基于C语法扩展的面向对象编程、及C++模板支持的泛型编程。
面向过程编程(Procedure Oriented)是以过程为中心,把分析解决问题的步骤流程以函数的形式一步步设计实现。
面向对象编程(OOP)是以事务为中心。一切事物皆对象,通过面向对象的方式,将现实世界的事物抽象成对象。
学习C++的主要注意的问题是:C++不是++C。
图3
C++对C的“增强”,主要表现在两个方面:
在原来面向过程的机制基础上,对C语言的功能做了不少扩充
增加了面向对象的机制
常变量
在变量的基础上加const限定: 存储单元中的值不允许变化。因此常变量又称为只读变量(read-only-variable)。
注意区别用#define命令定义的符号常量和用const定义的常变量。
强制类型转换
C语言强制类型转换的一般形式:(类型名)(表达式)
示例:(double)a (将a转换成double类型)
C++还增加了以下形式: 类型名(表达式)
示例:int(x);
int (x+y); 变量引用reference
对一个数据可以使用“引用”,这是C++对C的一个重要扩充,引用是一种新的变量类型,它的作用是为一个变量起一个别名
不能同时引用两个变量
C中函数之间的参数传递方式有:复制传递方式、地址传递方式;C++增加了函数参数引用
图4
内联函数
C++提供一种提高效率的方法,即在编译时将所调用函数的代码直接嵌入到主调函数中。这种嵌入到主调函数中的函数称为内置函数(inline function),又称内嵌函数或内联函数。后面讲解的面向对象高级概念中的类,可以在内部定义成员函数,也是内联函数(即没有显示加关键字inline)。
内联函数语法
inline 存储类型 数据类型 函数名(参数列表)
内联函数的限制
使用内联函数可以节省运行时间,但却增加了目标程序的长度。因此一般只将规模很小(一般为5个语句以下)而使用频繁的函数(如定时采集数据的函数)声明为内置函数。
由于多个源文件是分开编译的,要内联就应该把内联函数声明定义在头文件中。
内置函数中不能包括复杂的控制语句,如循环语句和switch语句。
函数重载(后面课程详细讨论)
C++允许用同一函数名定义多个函数,这些函数的参数个数和参数类型不同。这就是函数的重载(function overloading)。即对一个函数名重新赋予它新的含义,使一个函数名可以多用。
函数模板(后面课程详细讨论)
C++提供了函数模板(function template)。所谓函数模板,实际上是建立一个通用函数,其函数类型和形参类型不具体指定,用一个虚拟的类型来代表。这个通用函数就称为函数模int sun(int x)
{
return x+x;
}
int sum(int x, int y)
{
return x+y;
}
double sum(double x, double y, double z)
{
return x+y+z;
} 函数的默认参数
C++允许赋予函数参数默认值,即在调用该函数时,可以不写某些参数的值,编译器会自动把默认值传递给调用语句中。
默认值可以在声明或定义中设置;也可在声明或定义时都设置,都设置时要求默认值是相同的。
注意事项:
如果不是在声明中设置默认值,而在定义中设置,那么定义一定要放在函数调用之前
不能将实际值传递给引用类型的参数。可以将变量作引用类型参数的默认值,这时变量必须是已经声明且是全局变量
若给某一参数设置了默认值,那么在参数表中其后所有的参数都必须也设置默认值
在调用时,若给已经设置默认值的参数传递实际值,既要取代默认值,则在参数表中被取代参数的左边所定义的所有参数,无论是否有默认值,都必须传递实际参数
1.7再谈结构体
一般的,使用面向过程的设计方法,结构体主要是用于格式化数据,但从面向对象的角度来看,就是一种封装形式,这个是面向对象实现的基础,进一步熟悉结构体,离OOP的核心就近一步。
基本语法:
struct 结构体名{
成员域1;
成员域2;
…
};
C++语法中相对C语法增加了访问权限的概念,有三种:public、private及protected,默认是public。
public:公共成员,表示可以通过结构体变量对象直接访问到成员
private :私有成员,表示仅结构体成员函数可以使用的成员
protected:保护成员,表示被继承的派生对象可以访问使用的成员
由于增加访问权限,结构体变量就得增加构造函数的概念和this指针,不然成员函数访问成员数据就是问题。
|