C++程序设计教程修订版 第9章 引用
合集下载
c语言程序设计第9章课件
{ int a[3][4]={{0,1,2,3},{10,11,12,13},{20,21,22,23}}, i, j, *p;
for (p=a[0], i=0; i< 3; i++)
{ for (j=0; j< 4; j++)
printf("%4d",*(p+i*4+j)); /* 元素的相对位置为i*4+j */
1
C 语言程序设计
第8章 指 针
池州师专 计算机中心
第8章 指针
2
8.1 指针和指针变量 8.2 指针与数组 8.3 指针与函数
2019/6/16
8.1 指针和指针变量
8.1.1 指针和指针变量的概念
变量的两个物理意义 变量的内容 变量的地址
main()
x
{float x; int y;
…
}
y
3
2019/6/16
8.2 指针与数组
19
8.2.1 指向数组的指针
2. 二维数组的指针
a[0]+1 a[0]+2 a[0]+3
a[0]数组 0 1 2 3 a[1]数组 10 11 12 13 a[2]数组 20 21 22 23
⑵ 二维数组元素的地址
a[2]+1 a[2]+2 a[2]+3
a[0]、a[1]、a[2]是一维数组名, 所以a[i]+j是数组元素的地址。
a
赋值运算 p
main()
{int a,*p; x float x,*q;
p = &a;
q = &x;
… }
谭浩强 c语言程序设计(第九章)
形式1: #ifdef 标识符 程序段1 #else 程序段2 #endif 意义:若该标识 符已被#define 命令定义,则编 译程序段1,否 则编译程序段2 形式2: #ifndef 标识符 程序段1 #else 程序段2 #endif 意义:若该标识
符没有被#define 命令定义,则编 译程序段1,否则 编译程序段2
4
第九章 预处理命令
例:下列程序宏替换。
例 #include <stdio.h> #define N 2 #define M N+1 # define NUM (M+3)*M/2 void main() { int i; for (i=0; i<=NUM; i++); printf(“%d\n”,i); }
第九章 预处理命令
第九章 预处理命令
内容提要: ★宏定义
★文件包含
★条件编译
1
第九章 预处理命令 – 作用:对源程序编译之前做一些处理,生成扩展C 源程序 种类
• 宏定义 • 文件包含 • 条件编译 #define #include #if--#else--#endif等
– 格式:
• “#”开头 • 占单独书写行 • 语句尾不加分号
#ifdef DEBUG printf(“x=%d,y=%d,z=%d\n”,x,y,z); #endif
#define DEBUG
字符串(可为空)
调试时:加上此命令 调试完成后:删去此命令
15
第九章 预处理命令 例5: (选择性地编译不同功能) 。根据需要,有时要把 字母全改为大写输出,另一些时候则要把字母全改为 小写输出。如何适应这两种不同要求。
11
第九章 预处理命令
符没有被#define 命令定义,则编 译程序段1,否则 编译程序段2
4
第九章 预处理命令
例:下列程序宏替换。
例 #include <stdio.h> #define N 2 #define M N+1 # define NUM (M+3)*M/2 void main() { int i; for (i=0; i<=NUM; i++); printf(“%d\n”,i); }
第九章 预处理命令
第九章 预处理命令
内容提要: ★宏定义
★文件包含
★条件编译
1
第九章 预处理命令 – 作用:对源程序编译之前做一些处理,生成扩展C 源程序 种类
• 宏定义 • 文件包含 • 条件编译 #define #include #if--#else--#endif等
– 格式:
• “#”开头 • 占单独书写行 • 语句尾不加分号
#ifdef DEBUG printf(“x=%d,y=%d,z=%d\n”,x,y,z); #endif
#define DEBUG
字符串(可为空)
调试时:加上此命令 调试完成后:删去此命令
15
第九章 预处理命令 例5: (选择性地编译不同功能) 。根据需要,有时要把 字母全改为大写输出,另一些时候则要把字母全改为 小写输出。如何适应这两种不同要求。
11
第九章 预处理命令
C#-程序设计教程第9章
文本框TextBox 提供一个文本编辑区域,用于显示用户输
入或显示文本,常用属性为Text,默认事件为TextChanged,
当文本框中的文本发生变化时触发。此外还有KeyDown、
KeyPress和KeyUp事件,用于响应键盘按键事件。
可以通过设置Multiline属性为True使文本框变为多行,
2.事件
事件是用户和程序交互地一种最普遍的方式,事
件可由用户操作、程序代码或系统生成。例如,单击按 钮时会触发Click事件,加载窗体时会触发Load事件。
事件产生时会发送消息,并由专门的消息处理程序翻译 并处理消息。
通常,事件都是C#中预先设置好的、可以被对象
识别的操作。用户只需要补充事件处理代码,就可以完
1.Windows窗体项目结构 以下过程将创建一个Windows应用程序,并了解整个项目的
基本结构。实现步骤如下: (1)点击右下角“开始” “Visual Studio 2017” 打
开Visual Studio 2017开发环境。 (2)选择菜单“文件”“新建”“项目…”,打开“新
建项目”对话框,如图9-1所示。在左侧“项目类型”窗格中 选择“Windows桌面”,在右侧的“模板”窗格中选择 “Windows窗体应用(.NET Framework)”。
2022年10月4日星期二
2、设置窗体属性
【例9-3】在本任务中,将在【例9-2】的基础上,设置窗体的基本属性。实现步 骤如下:
(1)双击“解决方案资源管理器”中“Form1.cs”出现Form1所在的窗体。
(2)在“属性”窗口找到Text属性,将属性值改为“第一个窗体”,如图9-5所 示。
作。
2022年10月4日星期二
C语言程序设计 第3版 第9章 编译预处理
int s; s=sum(5); printf("s%d\n",s); }
#include "test2.c" static int sum(int n) {
int i,s=0; for(i=1;i<=n;i++)
s=s+fact(i); return s; }
static int fact(int n) {
C语言程序设计
第9章 编译预处理
第1讲:编译预处理基本形式
提纲
1.宏定义 2.文件包含 3.条件编译
1.宏定义
不带参数宏定义 带参数宏定义
格式:
#define 标识符 字符串
功能:
指定标识符代替一个较复杂的字符串。
注意说明:
(1)宏名一般习惯用大写字母,例如宏名PI。 (2)宏名用做代替一个字符串,不作语法检查。 (3)宏定义无需在末尾加“;” (4)宏定义的有效范围为#undef命令终止。 (5)在进行宏定义时,可以引用已定义的宏名。
char web[50]; int i=0; gets(web); while(web[i]!='\0') {
#if(R==1) if(web[i]>='A'&&web[i]<='Z') {web[i]=web[i]+32; i++;}
#else if(web[i]>='a'&&web[i]<='z') {web[i]=web[i]-32; i++;}
形式3:
#ifndef 标识符 程序段1
#else 程序段2
#include "test2.c" static int sum(int n) {
int i,s=0; for(i=1;i<=n;i++)
s=s+fact(i); return s; }
static int fact(int n) {
C语言程序设计
第9章 编译预处理
第1讲:编译预处理基本形式
提纲
1.宏定义 2.文件包含 3.条件编译
1.宏定义
不带参数宏定义 带参数宏定义
格式:
#define 标识符 字符串
功能:
指定标识符代替一个较复杂的字符串。
注意说明:
(1)宏名一般习惯用大写字母,例如宏名PI。 (2)宏名用做代替一个字符串,不作语法检查。 (3)宏定义无需在末尾加“;” (4)宏定义的有效范围为#undef命令终止。 (5)在进行宏定义时,可以引用已定义的宏名。
char web[50]; int i=0; gets(web); while(web[i]!='\0') {
#if(R==1) if(web[i]>='A'&&web[i]<='Z') {web[i]=web[i]+32; i++;}
#else if(web[i]>='a'&&web[i]<='z') {web[i]=web[i]-32; i++;}
形式3:
#ifndef 标识符 程序段1
#else 程序段2
Visual C++程序设计教程第九章
9.1.1数据库和DBMS
一个数据库系统,一般包括数据、数据库、数据 库管理系统、应用程序、数据库系统。其中数据 库管理系统是数据库系统的核心,主要功能如下:
数据定义功能:定义数据库的逻辑结构和数据库 对象。
数据查询功能:数据库检索。 数据操作功能:数据库的添加与修改。 数据控制功能:数据存取与更新、完整性与安全
SQL语言包括数据定义语言、数据查询语言、数据操纵语言和 数据控制语言等,下面详细介绍这些语言的使用方法。
1.SQL查询语句 SQL查询语句主要用于从数据库中检索数据。数据查询语言主
要包括SELECT等命令,SELECT命令的基本语法格式如下: SELECT<字段名>[字段名,…] FROM<表名> [WHERE<条件表达式>] [GROUP BY<字段名>[HAVING<函数表达式>]] [ORDER BY<字段名>[<次序>]]
9.1.3数据库访问模式
VC++6.0和数据库是两种不同的软件系统平台,为了实 现不同平台之间的数据交流,VC++6.0提供了对数据 库访问的全面支持,主要的数据库访问技术概括起来 有5种:
1.ODBC API; 2.MFC ODBC类; 3.MFC DAO类;(数据访问对象) 4.MFC的OLE/DB; 5.ActiveX数据对象(ADO)。
的数据类型不完全相同。
<完整性约束>:指定字段或表的完整性约束条件。
9.1.2结构化查询语言SQL
数据控制语句: 数据控制语句主要用于对基本表和视图进行授权,描述完整性
规则和控制事务。数据控制语句主要包括GRAND、COMMIT、 ROLLBACK等命令。在Visual C++6.0访问数据库中很少涉及 到部分内容,因此详细使用方法就不作介绍。
新编c程序设计第九章精选文档PPT课件
themegallery LOGO
2. 关于不带参数的宏定义的几点说明:
(1)宏名一般用大写字母表示,便于与变量名区别;一般将字符个数较多的 字符串用一个宏名替换,减少程序中多处引用字符串书写错误。
(2)宏定义是用宏名来表示一个字符串,在宏展开时以该字符串取代宏名, 这只是一种简单的代换, 预处理程序对它不作任何检查。如有错误,只能在编 译已被宏展开后的源程序时发现。
NUM宏展开: 2*N+1+1
再宏展开: 2*2+1+1
themegallery LOGO
4.带参宏定义
(1)带参宏定义格式:#define 宏名(形参表) 宏体 (2)带参宏调用格式:宏名(实参表) (3)宏展开:用宏调用提供的实参字符串,直接置换宏定义命 令行中相应形参字符串,非形参字符保持不变
可以引用已定义的 宏名,层层置换
printf(“ Input a radius: ");
scanf(“ %f", &r);
printf(“ length=%.2f,area=%.2f", L, AR);
printf(“ vo=%.2f\n", VO);
}
themegallery LOGO
3、无参宏的应用举例
themegallery LOGO
3、无参宏的应用举例
例 9.2在进行宏定义时,可以引用已定义的宏名。
#define PI 3.1415926
#define L PI*r*2 #define AR PI*r*r
在进行宏定义时,
#define VO main( ) { float r;
AR*r*4/3
main( ) { float r, s;
2. 关于不带参数的宏定义的几点说明:
(1)宏名一般用大写字母表示,便于与变量名区别;一般将字符个数较多的 字符串用一个宏名替换,减少程序中多处引用字符串书写错误。
(2)宏定义是用宏名来表示一个字符串,在宏展开时以该字符串取代宏名, 这只是一种简单的代换, 预处理程序对它不作任何检查。如有错误,只能在编 译已被宏展开后的源程序时发现。
NUM宏展开: 2*N+1+1
再宏展开: 2*2+1+1
themegallery LOGO
4.带参宏定义
(1)带参宏定义格式:#define 宏名(形参表) 宏体 (2)带参宏调用格式:宏名(实参表) (3)宏展开:用宏调用提供的实参字符串,直接置换宏定义命 令行中相应形参字符串,非形参字符保持不变
可以引用已定义的 宏名,层层置换
printf(“ Input a radius: ");
scanf(“ %f", &r);
printf(“ length=%.2f,area=%.2f", L, AR);
printf(“ vo=%.2f\n", VO);
}
themegallery LOGO
3、无参宏的应用举例
themegallery LOGO
3、无参宏的应用举例
例 9.2在进行宏定义时,可以引用已定义的宏名。
#define PI 3.1415926
#define L PI*r*2 #define AR PI*r*r
在进行宏定义时,
#define VO main( ) { float r;
AR*r*4/3
main( ) { float r, s;
《C语言程序设计》电子课件 第9章课件
Your site here
重 庆
9.2文件的打开与关闭
电
子 工
3.使用文件的方式
程
文件使用方式
意义
职
(1)文件使用方式由r、w、a、t、 rt(只读)
打开一个文本文件,只允许读数据
业
b,+六个字符拼成,各字符的含义
学 院
是:r(read):读;w(write):写; a(append):追加;t(text):文本文
计 算
行管理,把它们的输入、输出等同于对磁盘文件的读和写。
机
ASCII文件:也称为文本文件,这种文件在磁盘中存放时每
学 院
个字符对应一个字节,用于存放对应的ASCII码。
二进制文件:是按二进制的编码方式来存放文件的。
Your site here
重
9.1文件概述
庆
电
子
工 程
2.文件类型指针
职
用一个指针变量指向一个文件,这个指针称为文件指针。
学
院
9.1文件概述
9.2文件打开与关闭
计 算
9.3文件的读写
机
9.4文件检测函数
学
院
Your site here
重
第九章 文件
庆
电
子
工 程
9.1概述
职 业
“文件”是指一组相关数据的有序集合。这个
学 院
数据集有一个名称,叫做文件名。实际上在前
面的各章中我们已经多次使用了文件,例如源
程序文件、目标文件、可执行文件、库文件
业
学
院
说明文件指针的一般形式如下:
FILE * 指针变量标识符
计
FILE *fp;
《C++程序设计》电子教案第9章 多态性和虚函数
返回本节
9.1.3 派生类指针
指向基类和派生类的指针是相关的。 例如: A * p ; // 指向类型 A 的对象的指针 A A_obj ; // 类型 A 的对象 B B_obj ; // 类型 B 的对象 p = & A_obj ; // p 指向类型 A 的对象 p = & B_obj ; // p 指向类型 B 的对象,它是 A 的派生类
((B_class *)p)->show_phone( ); // 用基类指针访问公有派生类的特定成员,必须进行类型转换 } 此程序的运行结果为: Zhang San Li Si
0731_12345678 0731_12345678
例9-9:写出下面的程序的执行结果。 #include <iostream.h> class Student { public: Student(int xx) { x=xx; } virtual float calcTuition( ); protected: int x; }; float Student::calcTuition() { return float(x*x);
main ( ) { A_class *p; //对象指针 A_class A_obj; //对象 B_class * bp; B_class B_obj; p=&A_obj; //P指针指向基类对象,调用基类成员函数 p->put_name("Zhang San"); p=& B_obj; //P指针指向派生类对象,调用继承自基类的成 员函数 p->put_name("Li Si"); A_obj.show_name( ); B_obj.show_name( ); bp=&B_obj; bp->put_phone("0731_12345678"); bp->show_phone( );
航空工业出版社 C++程序设计教程第9章
2.派生类的析构函数 派生类析构函数没有函数类型、没有参数,其定义及使用 方法与一般类的析构函数相同。派生类的析构函数用来对派生 类中所增加的成员进行清理工作,同时系统会自动调用基类的 析构函数和子对象的析构函数,对基类和子对象进行清理。 析构函数的调用顺序与构造函数正好相反:先执行派生类 的析构函数,然后调用子对象的析构函数,最后调用基类的析 构函数,对基类进行清理。
第9章
继承与派生
本章内容提要
9.1 类的继承与派生概述 9.2 多重继承 9.3 虚基类
9.1 类的继承与派生概述
9.1.1 继承与派生的概念
所谓继承,就是在一个已有类的基础上建立一个新类,已 有的类称为“基类”或“ቤተ መጻሕፍቲ ባይዱ类”,新建立的类称为“派生类” 或“子类”。 如果一个派生类只从一个基类派生,称为单继承;如果一 个派生类从多个基类派生,称为多重继承。
//定义基类Destination类 //定义数据成员为protected
//定义基类的默认构造函数
Destination(char f[],char t[]) { strcpy(from,f); strcpy(to,t); } ~ Destination() { cout<<"析构Destination类!"<<endl; } void getdata() { cout<<"输入发话地点/收话地点:"; cin>>from>>to; } void disp() { cout<<"计费从 "<<from<<" 到 "<<to; } }; class Time { protected: int hour,minute,second; int time;
C++语言程序设计:第9、10、11、12、13章
线 if (alist == NULL) Error(memoryAllocationError);
性 T* srcptr = X.alist; // X.alist是对象X的数组首地址
群
T* destptr = alist; // alist是本对象中的数组首地址
while (n--)
// 逐个复制数组元素
using namespace std; // 结构体Student struct Student {
int id; //学号 float gpa; //平均分 };
9
template <class T> //类模板:实现对任意类型数据进行存取
class Store { private:
T item; // 用于存放任意类型的数据 int haveValue; // 用于标记item是否已被存入内容 public: Store(void); // 默认形式(无形参)的构造函数 T GetElem(void); //提取数据函数 void PutElem(T x); //存入数据函数 };
if (size != n)
问
{ delete [] alist; alist = new T[n];
的 线
if (alist == NULL) Error(memoryAllocationError); size = n; }
性
T* destptr = alist; T* srcptr = rhs.alist;
12
C++语言程序设计
第二部分—群体数据
线性群体
– 线性群体的概念 – 直接访问群体--数组类 – 顺序访问群体--链表类 – 栈类 – 队列类
c#程序设计教程 课件第9章
执行后,将输出如下结果: 执行后,将输出如下结果: 需要注意的是,线程关联的方法必须与所使用的委托类型相一致, 需要注意的是,线程关联的方法必须与所使用的委托类型相一致, 这是关联方法f()的线程 这是关联方法 返回类型必须为void,且在创建委托对象时关联的方法必须是已 返回类型必须为 的线程 , 这是关联方法g()的线程 的线程: 这是关联方法 的线程:200 经确定了的。这些方法通常是类的静态方法和对象的方法。 经确定了的。这些方法通常是类的静态方法和对象的方法。
本文由x4168138贡献
ppt文档可能在WAP端浏览体验不佳。建议您优先选择TXT,或下载源文件到本机查看。
第9章 多线程
本章内容
9.1 一个简单的多线程应用程序 9.2 线程及其实现方法 9.3 线程的同步控制 9.4 线程池 9.5 线程对控件的访问
9.2 线程及其实现方法
9.2.1 线程的概念 线程和进程的主要区别在于: 线程和进程的主要区别在于:
C#程序设计教程——蒙祖强编著
进程是由多个线程组成,即线程是进程的一个组成部分。 进程是由多个线程组成,即线程是进程的一个组成部分。 线程的划分尺度小,具有较高的并发效率。 线程的划分尺度小,具有较高的并发效率。 进程独占相应的内存和资源(其他进程不能使用),线程则是 进程独占相应的内存和资源(其他进程不能使用),线程则是 ), 共享进程所拥有的内存和资源(其他线程也可以使用), ),从而极 共享进程所拥有的内存和资源(其他线程也可以使用),从而极 大地提高运行效率。 大地提高运行效率。 进程提供多个线程执行控制,而每个线程只能有一个运行入口、 进程提供多个线程执行控制,而每个线程只能有一个运行入口、 顺序执行序列和出口( 线序”执行)。 顺序执行序列和出口(“线序”执行)。 进程可以独立执行,但线程不能独立执行, 进程可以独立执行,但线程不能独立执行,而必须依赖于进程 所提供的环境。 所提供的环境。
本文由x4168138贡献
ppt文档可能在WAP端浏览体验不佳。建议您优先选择TXT,或下载源文件到本机查看。
第9章 多线程
本章内容
9.1 一个简单的多线程应用程序 9.2 线程及其实现方法 9.3 线程的同步控制 9.4 线程池 9.5 线程对控件的访问
9.2 线程及其实现方法
9.2.1 线程的概念 线程和进程的主要区别在于: 线程和进程的主要区别在于:
C#程序设计教程——蒙祖强编著
进程是由多个线程组成,即线程是进程的一个组成部分。 进程是由多个线程组成,即线程是进程的一个组成部分。 线程的划分尺度小,具有较高的并发效率。 线程的划分尺度小,具有较高的并发效率。 进程独占相应的内存和资源(其他进程不能使用),线程则是 进程独占相应的内存和资源(其他进程不能使用),线程则是 ), 共享进程所拥有的内存和资源(其他线程也可以使用), ),从而极 共享进程所拥有的内存和资源(其他线程也可以使用),从而极 大地提高运行效率。 大地提高运行效率。 进程提供多个线程执行控制,而每个线程只能有一个运行入口、 进程提供多个线程执行控制,而每个线程只能有一个运行入口、 顺序执行序列和出口( 线序”执行)。 顺序执行序列和出口(“线序”执行)。 进程可以独立执行,但线程不能独立执行, 进程可以独立执行,但线程不能独立执行,而必须依赖于进程 所提供的环境。 所提供的环境。
精品课件-C++程序设计-第9章
增加一些新的属性来创建一个全新的类。
int size;
…
};
第9章 继承
class Body {
public: double width; …
};
class Tail { public:
double length; … };
//定义Body类 //定义Tail类
继承在使用已存在的类时,可以根据自身的需求对其进 行修改和增加,以满足特定的要求。组合在对已存在的类进行使 用时,只能原封不动地将其实例化,并且将实例化的对象拿过来 使用,而不能做任何修改,所以这在一定程度上也显示了组合在 代码重用方面的局限性。当然,如果需要对一个类进行较大的修 改而不是扩展的时候,继承就不如构造一个新的类了。
public: int c; A(){a = 1; b = 2; c =3;} void setA(int a){this->a = a;} void setB(int b){this->b = b;}
第9章 继承
void setC(int c){this->c = c;} void print(){cout << "a=" << a << endl << "b=" << b << endl << "c=" << c << endl;} };
9.1 继承与组合 9.1.1 继承的概念与语法
图9.1呈现了生活中比较常见的交通工具的类层次。最 顶部的“交通工具”可称为“基类”或“父类”,这个基类有 三个子类(也可以称为“派生类”),分别为“空中交通工具”、 “陆地交通工具”和“水上交通工具”,称这些子类是从基类 继承而来的。而其中“陆地交通工具”还有它自己的子类,这 就涉及到了多级继承的问题。在这个结构图中,有四层类结构, 其中包含了三层继承关系。这里,每个子类都是其基类的特定 化版本。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
什么能被引用
对常量(用const声明)的引用 void main(void) { const int &r=8; //说明r为常量,不可赋值 cout << "r=“ << r<<endl; // r+=15; //r为常量,不可作赋值运算 cout << "r=“ << r<<endl; }
C ++ 程序设计教程(修订版)
第九章 引用
清华大学出版社
讲师:王磊
钱 能
9.1 引用概念 9.2 引用操作 9.3 什么能被引用 9.4 用引用传递函数参数 9.5 返回多个值 9.6 用引用返回值 9.7 函数调用作为左值 9.8 用const限定引用
9.9 返回堆中变量的引用
理解引用以及访问操作 理解引用与函数参数传递 理解函数返回引用的含义
返回堆中变量的引用
可以用动态分配的内存空间来初始化一个引用变量 float &reff=* new float; //用new开辟一个空间,取一个别名reff reff= 200; //给空间赋值 cout << reff; //输出200 delete &reff; //收回这个空间 这个空间只有别名,但程序可以引用到。 float *p, a;
例
void main(void) {
int a=3, b=5;
const int *pa=&b; pa=&a; *pa=10; a=100; } //可以不赋初值 //指针变量可以重新赋值 //非法,指针指向的内容不能赋值 //变量可以重新赋值
cout <<*pa << endl; //输出3
cout <<*pa << endl; //输出100
如:int r=6; int * const pr=&r; 则指针pr被禁写,即pr将始终指向一个地址,成为一个指针常 量,它将不能再作为左值而放在赋值号的左边 同样,禁写指针一定要在定义的时候赋初值 虽然指针被禁写,但其间接引用并没有被禁写,即可以通过pr 对r赋值: 如:*pr=8;
b y
5 3
3
3
引用与函数参数对比指针
引用作为形参,实参是变量而不是地址,这与指针变量作形参 不一样
void change(int *x, int *y) { int t; t=*x; *x=*y; *y=z; void change(int &x, int &y) } { int t; void main(void) 形参为指针变量 t=x; x=y; y=z; { int a=3,b=5; } change(&a,&b); //实参为地址 形参为整型引用 void main(void) cout<<a<<‘\t’<<b<<endl; { int a=3,b=5; } change(a,b); //实参为变量 a 3 b 5 5 3 cout<<a<<‘\t’<<b<<endl; }
1. 指针是通过地址间接访问某个变量,而引用是通 过别名直接访问某个变量 2. 引用必须初始化,而一旦被初始化后不得再作为 其它变量的别名
什么能被引用
如一个变量声明为T类型的引用,它必须用T类型的变量或对 象,或能转换成T类型的对象初始化 如果T类型引用的初始化值不是一个左值,将建立一个T类型 的目标并初始化,那个目标的地址变为引用的值??? 因指针也是变量,可以有指针变量的引用
int &f(int &x) { static int t=2; t=x++; return t; } void main(void) { int a=3; cout<<f(a)<<endl; f(a)=20; a=a+5; cout<<f(a)<<endl; a=f(a); cout<<f(a)<<endl; }
x &a t
3
&b
y
void dd(int &x, int &y, int z)
{
x=x+z;
y=y-x; z=10;
x=8 y=-4
x=13 y=-17
z=10z=10来自cout<<“(2)”<<x<<‘\t’<<y<<‘\t’<<z<<en dl; (2) 8 -4 10 void main(void) } (2) 13 -17 10 { int a=3,b=4,c=5; (1) 13 -17 5 for(int i=0;i<2;i++) dd(a,b,c); cout<<“(1)”<<a<<‘\t’<<b<<‘\t’<<c<<endl; }
输出 3 a=4 t=3 t=20 a=5 a=10 输出 10 a=11 a=11
输出 11 a=12
用const限定引用
当用const限制说明标识符时,表示所说明的数据类型为常量 类型 可分为const型常量和const型指针 可用const限制定义标识符量,如: const int MaxLine =1000; const float Pi=3.1415926 用const定义标识符常量时,一定要对其初始化。在定义时进 行初始化是对这种常量置值的唯一方法 ,不能用赋值运算符 对这种常量在定义后再进行赋值。如: MaxLine =35; 保证实参不被修改的办法是传递const的指针或引用
例 int *a, b=8; int * & p=a; p=&b;
以下的声明是非法的:
1、企图建立引用的数组 2、企图建立指向引用的指针 3、企图建立引用的引用 4、企图建立void应用 5、用类型或NULL来初始化 int & a[9]; int & *p; int & &px; void & a=x; int & a=int; int & a =NULL;
void f1( int *px) { *px+=10;}
void f2(int &xx) { void main(void) { int x=0; cout<<"x="<<x<<endl; f1(&x); cout<<"x="<<x<<endl; f2(x); cout<<"x="<<x<<endl; x=0 x=10 x=20 xx+=10;}
即不可以通过指针对变量重新赋值
用const限定引用
(3)禁写指针又禁写间接引用 将上面两种情况结合起来,声明语句: const 数据类型 *const 指针变量名; 如:const int *const px=&x 说明:px是一个指针常量,它指向一禁写的实体,并且指针 本身也被禁写,诸如:px= *px= 此类的语句都是非法的 其在定义时必须赋初值
理解用const修饰引用
掌握对堆的引用
引用
引用:对变量起另外一个名字(外号) 定义:类型 &引用变量名 = 原变量名; 其中原变量名必须是一个已定义过的变量
int max; int &refmax=max;
refmax并没有重新在内存中开辟单元,只是引用max的单元 max与refmax在内存中占用同一地址,即同一地址两个名字 对引用的修改实际就是对引用目标的修改
例
void main(void)
{
int a,b; int *const pa=&a; //一定要赋初值,pa是常量,不能在程序中被改变 *pa=10; pa=&b; } //可以间接引用 //非法,pa为常量
pa &a
a
b
10
用const限定引用
(2)禁写间接引用 声明语句格式:const 数据类型 * 指针变量名; 所声明的指针指向一禁写的实体,即间接引用不能被改写 如:int a; const int *p=&a; 所以程序中不能出现如 *p= 的语句,但指针p并未被禁写, 因而可对指针p进行改写 如:int b; p=&b;
p=new float; float a=* new float; 错误!
引用
当&a的前面有类型符时(如int &a),它必然是对引用
的声明;如果前面无类型符(如cout<<&a;),则是取
变量的地址
引用的操作
对引用执行取地址操作,结果只能是所引用的目标地址 C++没有提供访问引用本身地址的方法,因为它与指针或其 他变量的地址不同,没有任何意义
指针与引用的区别:
引用与函数参数
引用的用途主要是用来作函数的参数或函数的返回值 引用作函数的形参,实际上是在被调函数中对实参变量进行 操作
void change(int &x, int &y) //x,y是实参a,b的别名 { int t; a 3 5 t=x; x=y; y=z; x } void main(void) t { int a=3,b=5; change(a,b); //实参为变量 cout <<a <<‘\t’ <<b <<endl; 输出: 5 }