2.68k likes | 2.86k Views
C++ 语言编程. 宁 博. 程序设计方法的发展历程. 面向过程的程序设计方法 程序的目的:用于数学计算 主要工作:设计求解问题的过程 缺点:对于庞大、复杂的程序难以开发和维护. 程序设计方法的发展历程. 面向过程的结构化程序设计方法 设计思路 自顶向下、逐步求精。采用模块分解与功能抽象,自顶向下、分而治之 程序结构 按功能划分为若干个基本模块 各模块间的关系尽可能简单,功能上相对独立;每一模块内部均是由顺序、选择和循环三种基本结构组成 其模块化实现的具体方法是使用子程序. 程序设计方法的发展历程. 面向过程的结构化程序设计方法 优点
E N D
C++语言编程 宁 博
程序设计方法的发展历程 • 面向过程的程序设计方法 • 程序的目的:用于数学计算 • 主要工作:设计求解问题的过程 • 缺点:对于庞大、复杂的程序难以开发和维护
程序设计方法的发展历程 • 面向过程的结构化程序设计方法 • 设计思路 • 自顶向下、逐步求精。采用模块分解与功能抽象,自顶向下、分而治之 • 程序结构 • 按功能划分为若干个基本模块 • 各模块间的关系尽可能简单,功能上相对独立;每一模块内部均是由顺序、选择和循环三种基本结构组成 • 其模块化实现的具体方法是使用子程序
程序设计方法的发展历程 • 面向过程的结构化程序设计方法 • 优点 有效地将一个较复杂的程序系统设计任务分解成许多易于控制和处理的子任务,便于开发和维护。
程序设计方法的发展历程 • 面向过程的结构化程序设计方法 • 缺点:可重用性差、数据安全性差、难以开发图形界面的应用 • 把数据和处理数据的过程相互独立 • 当数据结构改变时,所有相关的处理过程都要进行相应的修改 • 图形用户界面的应用,很难用过程来描述和实现,开发和维护都很困难
面向对象的设计思想 • 面向对象的程序设计方法 • 将数据及对数据的操作方法封装在一起,作为一个相互依存、不可分离的整体——对象。 • 对同类型对象抽象出其共性,形成类。 • 类通过一个简单的外部接口,与外界发生关系 • 基本设计思想 • 封装 • 软件复用
面向对象的设计思想 • 面向对象的程序设计方法 • 优点 • 程序模块间的关系更为简单,程序模块的独立性、数据的安全性就有了良好的保障。 • 通过继承与多态性,可以大大提高程序的可重用性,使得软件的开发和维护都更为方便
面向对象的基本概念 ---- 对象 • 一般意义上的对象 • 是现实世界中一个实际存在的事物。 • 可以是有形的(比如一辆汽车),也可以是无形的(比如一项计划)。 • 是构成世界的一个独立单位,具有: • 静态特征:可以用某种数据来描述 • 动态特征:对象所表现的行为或具有的功能
面向对象的基本概念 ---- 对象 • 面向对象方法中的对象 • 是系统用来描述客观事物的一个实体,它是用来构成系统的一个基本单位。对象由一组属性和一组行为构成。 • 属性:用来描述对象静态特征的数据项。 • 行为:用来描述对象动态特征的操作。
面向对象的基本概念 ---- 类 • 分类——人类通常的思维方法 • 分类所依据的原则——抽象 • 忽略事物的非本质特征,只注意那些与当前目标有关的本质特征,从而找出事物的共性,把具有共同性质的事物划分为一类,得出一个抽象的概念。 • 例如,石头、树木、汽车、房屋等都是人们在长期的生产和生活实践中抽象出的概念。
面向对象的基本概念 ---- 类 • 面向对象方法中的"类" • 具有相同属性和行为的一组对象的集合 • 为属于该类的全部对象提供了抽象的描述,包括属性和行为两个主要部分。 • 类与对象的关系:犹如模具与铸件之间的关系,一个属于某类的对象称为该类的一个实例。
面向对象的基本概念 ---- 封装 • 把对象的属性和行为结合成一个独立的系统单位 • 尽可能隐蔽对象的内部细节。对外形成一个边界(或者说一道屏障),只保留有限的对外接口使之与外部发生联系。
面向对象的基本概念 ---- 继承 • 继承对于软件复用有着重要意义,是面向对象技术能够提高软件开发效率的重要原因之一。 • 定义:特殊类的对象拥有其一般类的全部属性与行为,称作特殊类对一般类的继承。 • 例如:将Person作为一个一般类,Student便是一个特殊类。
面向对象的基本概念 ---- 多态性 • 多态性是指在一般类中定义的属性或行为,被特殊类继承之后,可以具有不同的数据类型或表现出不同的行为。这使得同一个属性或行为在一般类及其各个特殊类中具有不同的语义。 • 例如: 数的加法->实数的加法->复数的加法
C++语言概述 • C++语言的产生 • C++的特点 • 一个简单的C++程序实例
C++语言的产生 • C++是从C语言发展演变而来的,首先是一个更好的C。 • 引入了类的机制,最初的C++被称为"带类的C"。 • 1983年正式取名为C++。C++语言的标准化工作从1989年开始,于1994年制定了ANSI C++标准草案。以后又经过不断完善,成为目前的C++。
C++的特点 • 全面兼容C • 它保持了C的简洁、高效和接近汇编语言等特点 • 对C的类型系统进行了扩充 • C++也支持面向过程的程序设计,不是一个纯正的面向对象的语言 • 支持面向对象的方法 • 类、对象、继承、抽象、封装、….
一个简单的C++程序实例 #include <iostream.h> void main(void) { cout<<"Hello!\n"; cout<<"Welcome to c++!\n"; }
一个简单的C++程序实例 运行结果: Hello! Welcome to c++!
注释 • C中的注释:块注释 /* */ • /* This is a comment */ • 不允许嵌套 • C++中的注释 • C++继承了C的块注释方式 • 增加了一种行注释方式 • C++把任何一行中从“//”开始直到该行结束的所有内容皆视为注释
注释 ---- 一个简单的例子 #include <stdio.h> #include <conio.h> void main() { // Checking if a keyword is ESC int i, key; while( 1 ) { key = getch(); // Get a key from console if (key == ‘\x1B’ { printf(“\nEscape! ”); return; } else printf(“\nKeycode is %2XH”, key); } }
作用域 • 模块:在C语言中模块的概念是指在花括号{}之间的一组语句 • 作用域的种类 • 局部模块作用语:变量定义在模块范围内 • 文件作用域:变量定义在全局范围内,只限于当前文件的存取; • 全局作用域:变量定义在全局范围内,对全程序有效。实现方式:include和extern • 类作用域:变量定义在类中,在类范围内有效
作用域 : : 运算符: 指明作用域。 例 int x; void f() { int x=1; ::x=2; return; }
作用域 ---- 一个简单的例子 #include <stdio.h> int global = 10; void main() { int global = 5; printf(“The value of global is : %d\n”, global); return; }
作用域 ---- 作用域分辨操作符 • 全局变量访问 • ::global #include <stdio.h> int global = 10; void main() { int global = 5; printf(“The value of inner global is : %d\n”, global); printf(“The value of outer global is : %d\n”, ::global); return; }
指针 • 指针是C语言的一个非常重要的特征 • 实际上是内存地址,非常灵活且非常高效 • 但又潜伏着非常大的危险性 • 具有数据类型,可以进行指针运算 • 无值型指针,void *,是一种非常有用且十分灵活的指针类型
常量指针 • 定义格式 const type * ptr_name; • 其含义是指向常量的指针 • 不允许通过指针来修改其指向的对象的值 • 可以修改指针的值 • 例子 const int * ptr; const int i=10; ptr = & i; // 修改指针的值 *ptr = i+10; // 错误操作,试图修改指针指向的内容
常量指针 • 例子 const char * ptr; const char str[10]=“hehehe”; ptr = str; // 指针赋值 ptr[3] = ‘’; // 错误操作,试图修改指针指向的内容
常量指针 const int * ptr; int i=10; ptr = &i; // 指针赋值, 等价于(const int *)&i *ptr = 15; // 错误操作,试图修改指针指向的内容 i++; cout << “i = ” << *ptr << endl; 输出结果为:11
常量指针 • 不允许将const类型的变量地址赋值给一般的变量指针 int * ptr; const int i = 10; ptr = &i; // 编译错误 ptr = (int *)&i; // 正确 *ptr = *ptr + 1; cout << “i = ” << *ptr << endl; 输出结果为:11
指针常量 • 定义格式 type * const ptr_name; • 其含义是指针变量的值不可改变 • 不允许修改指针变量的地址值 • 可以修改指针指向的变量值,如果指向的对象不是一个常量的话 • 例子 • int * const ptr1; • void * const ptr2;
指针常量 • int num=10; • int * const const_ptr = # • const int * ptr_to_const = # • int const * ptr = # • const_ptr =(int * const) & num; // 编译错误 • //试图修改一个指针常量的地址值 • *ptr = num; // 编译错误 • //试图修改常量指针指向的对象值
void类型 1.说明函数没有返回值; void fun(void) { return ;} 2.表示函数不需要任何入口参数; double fun(void) { } 3.可将指针说明为void型。这种指针可被赋以其它任何类型的指针。 double a=9.0; double *pd=&a; void *p; p=pd;
练习 用指针写一个swap函数,交换两个整数 a和b的值。打印交换前后a,b的值。
引用 • 先看一个简单的例子 int i, &j=i; i=1; cout<<“i=” <<i<<endl; // output: i=1 j++; cout<<“i=” <<i<<endl; // output: i=2 i++; cout<<“j=” <<j<<endl; // output: j=3
引用 • 引用的定义格式 • type & ref_name = var_name; • 引用定义说明 • 引用必须在定义时进行初始化 • 被引用的变量必须在引用定义之前定义 • 引用一经定义,便无法重新引用其它变量
引用 • 对引用概念的理解 • int i=10, &j=i; • 在物理存储中,变量i有存储单元,但引用j没有存储单元,其具体表现是变量i和引用j的物理地址是相同的 • 内存单元 0XEFFF21 有两个名字,可以将引用j理解为变量i的别名 • 在同一个模块中的引用没有太大意义,但在函数调用时可以实现传名调用 变量i 10 0XEFFF21 引用j
练习 用引用写一个swap函数,交换两个整数 a和b的值。打印交换前后a,b的值。
C++的内存格局 • 全局数据区(data area) • 代码区(code area) • 栈区(stack area) • 堆区(heap area)
C++的内存格局 全局变量、静态数据、常量存放在全局数据区; 所有类成员函数和非成员函数代码存放在代码区; 为运行函数而分配的局部变量、函数参数、返回数据、返回地址等存放在栈区; 其余的空间都被称为堆区。
堆内存的分配与释放 当程序运行到需要一个动态分配的变量或对象时,必须向系统申请取得堆中的一块所需大小的存贮空间,用于存贮该变量或对象。当不再使用该变量或对象时,也就是它的生命结束时,要显式释放它所占用的存贮空间,这样系统就能对该堆空间进行再次分配,做到重复使用有限的资源。 在C++中,申请和释放堆中分配的存贮空间,分别使用new和delete的两个运算符来完成,其使用的格式如下: 指针变量名=new 类型名(初始化式); delete 指针名; new运算符返回的是一个指向所分配类型变量(对象)的指针。对所创建的变量或对象,都是通过该指针来间接操作的,而动态创建的对象本身没有名字。
堆内存的分配与释放 C中的malloc和free函数在C++中可以用 alloc.h头文件中声明 void * malloc(size_t size); void free(void *);
堆内存的分配与释放 if ((array=(int*)malloc(arraysize*sizeof(int)))==NULL) { cout<<“can’t allocate more memory.\n”; exit(1); } … free(array);
堆内存的分配与释放 new new 类型名T(初值列表) 功能:在程序执行期间,申请用于存放T类型对象的内存空间,并依据初值列表调用合适的构造函数。 结果值:成功:T类型的指针,指向新分配的内存。失败:0(NULL)
堆内存的分配与释放 • delete delete 指针P 功能:释放指针P所指向的内存。P必须是new操作的返回值。
堆内存的分配与释放 1.用初始化式(initializer)来显式初始化 例如: int *pi=new int(0); 2.当pi生命周期结束时,必须释放pi所指向的目标: delete pi; 注意这时释放了pi所指的目标的内存空间,也就是撤销了该目标,称动态内存释放(dynamic memory deallocation),但指针pi本身并没有撤销,它自己仍然存在,该指针所占内存空间并未释放。 堆 0 Pi
堆内存的分配与释放 1.用初始化式(initializer)来显式初始化 例如: int *pi=new int(0); 2.当pi生命周期结束时,必须释放pi所指向的目标: delete pi; 注意这时释放了pi所指的目标的内存空间,也就是撤销了该目标,称动态内存释放(dynamic memory deallocation),但指针pi本身并没有撤销,它自己仍然存在,该指针所占内存空间并未释放。 堆 Pi
堆内存的分配与释放 对于数组进行动态分配的格式为: 指针变量名=new 类型名[下标表达式]; delete [ ] 指向该数组的指针变量名;
堆内存的分配与释放 if ((array=new int [arraysize])==NULL) { cout<<“can’t allocate more memory.\n”; exit(1); } … delete [] array;
堆内存的分配与释放 【例】动态数组的建立与撤销 #include <iostream.h> #include <string.h> void main(){ int n; char *pc; cout<<"请输入动态数组的元素个数"<<endl; cin>>n; pc=new char[n]; // strcpy(pc,"堆内存的动态分配"); cout<<pc<<endl; delete []pc; // 撤销并释放pc所指向的n个字符的内存空间 return ;}