




已阅读5页,还剩87页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
面向对象程序设计(VC+)复习纲要考试时间:第16周星期五56节考试地点:二教404第1章 Visual C+集成开发环境第2章 C+语言基础2-1 C+的变量和表达式C+的变量在被引用之前必须被定义;可以在程序中随时定义;但不允许重复定义一个变量;变量定义后若没有被初始化,则这个变量中的值是随机的。2-1-1 设有语句char s=”abc0endl”; int m=sizeof(s),n=strlen(s);则m、n的值分别为9和3,请问为什么?sizeof连“/0”都计算;strlen遇到”/0”停止;2-1-2 C+语言中数组元素的访问方式有两种,即:下标方式和指针方式 。 2-1-3 设有int a,b;执行语句:b=(a=2+3,a*4),a+5;后,a+b的值是多少?252-1-4 已知有定义 “int x, a =15,17,19, *pa=a;”,在执行“x=*pa+;”后,*pa的值是17,为什么?地址2-2 C+数据类型2-2-1 设pointer1和pointer2是指向同一个int型一维数组的指针变量,i为int型变量,语句 pointer2=i是否正确? 正确 基类型相同2-3 控制语句2-3-1 语句if(w) ; else ; 中的表达式w的等价表示是什么?我!=02-3-2 for循环for(int i(0),j(10);i=j=4;i+,j- -)的循环体执行多少次?2-3-3 break和continue语句的作用。BreaK终止整个循环continue结束本次循环2-3-4 switch语句switch后面的表达式一般只能是整型、字符型或枚举型;每一个常量表达式的值都是唯一的;default是可选项;case后面的语句可以不要花括号;如果switch中只有一个case常量表达式,则可以省略花括号。2-4 函数定义、函数声明和函数调用使用函数之前,首先要定义该函数。编写一个实现特定功能的函数代码就称为函数定义。 函数定义的一般形式是: ()存储类型:static、extern,默认extern; 函数类型:函数返回值的类型,默认int; 函数名:定义函数的名称; 形参表:用逗号分隔的变量声明列表; 函数体:一系列语句,用于实现函数的功能。所谓函数调用是指执行一个函数的函数体代码。调用某个函数的函数称为主调函数,被调用的函数称为被调函数。函数调用的语法形式为: (实参1,实参2,实参n)C+允许函数调用在前,函数定义在后,但此时要求在函数调用前必须先进行函数的声明,以告诉编译器该函数是在其它地方定义的。函数声明的一般形式如下: ();2-5 设函数int min(int, int)返回两参数中最小值,利用此函数求三个整数的最小值2-6 C+函数参数的传递方式C+函数参数的传递方式有三种:值传递、按地址传递和引用传递。值传递是一种单向的参数传递方式,即只把实参的值传递给形参,形参值的变化不影响实参。例2-16实参与形参的值传递。调用函数后,实参a、b的值并没有发生改变。 #include void swap(int x, int y)/函数定义 cout x=x y=yendl;int temp = x;/交换形参x和y x = y;y = temp;coutafter swap:endl;cout x=x y=yendl;main()int a = 20, b = 40;coutbefore swap:endl;cout a=a b=bendl;swap(a, b);/函数调用 cout a=a b=bendl; 按地址传递方式,函数定义以指针作为函数的形参,函数调用的实参必须是指针变量或变量的地址,形参的任何变化都将影响实参。例2-17实参与形参按地址传递,以指针作为函数参数。 #include void swap(int*, int*);/ 函数声明 main( )int a = 20, b = 40;swap(&a, &b);/ 地址作为函数实参 couta=a, b=bendl;void swap(int* px, int* py)/ 指针作为函数形参 int temp = *px;/ “*px”表示px所指单元的内容 *px = *py;*py = temp;按引用传递方式,函数定义时使用引用作为形参,函数调用时直接使用一般变量作为实参,被调函数对引用的任何修改都将影响主调函数的实参。例2-20引用作为参数。 #include void swap(int&, int&);/ 函数声明 main()int a = 20, b = 40;swap(a, b);couta=a, b=bendl;void swap(int& x, int& y) / 引用作为函数形参 int temp = x;x = y;y = temp; 2-6-1 写出下列程序运行结果: #include iostream.h void swap1(int*, int*);void swap2(int*, int*);void main( )int x=5, y=8, *px, *py;px=&x, py=&y; if(xy) swap1(px,py); coutafter swap1: *px=*px,*py=*pyendl;if(xy) swap2(px,py); coutafter swap2: *px=*px,*py=*pyendl; void swap1(int *p,int *q) int *t; t=p; p=q; q=t; void swap2(int *p,int *q) int t; t=*p;*p=*q;*q=t; 运行结果:after swap1: *px=5, *py=8after swap2: *px=8, *py=52-7 在函数定义中为形参指定默认值C+允许在函数声明或函数定义时为形参指定一个默认值。在调用此类含默认值形参的函数时,如果形参有对应的实参,则将实参传递给形参;如果省略了实参,则将上述默认值传递给形参。 如果函数有多个形参,则声明和定义函数时,必须将带缺省值的形参放在参数表的右部,即在带缺省值的形参的右边不能有未指定缺省值的形参。2-8 内联函数在调用函数时,系统要进行现场处理工作,需要占用附加的现场处理时间。若把函数体直接嵌入函数调用处,则可消除附加的现场处理的时间开销,提高程序的运行效率。C+提供了实现上述嵌入功能的函数,这种函数称为内联(inline)函数。定义一个内联函数只需在函数头前加入关键字inline。当编译程序遇到内联函数调用语句时,就会将该内联函数的函数体替换调用语句。当然,这样将会加大代码占用内存的空间开销,因此,内联函数一般适用于代码较短的函数。 使用内联函数时应注意以下几个问题: (1) 在一个文件中定义的内联函数不能在另一个文件中使用。它们通常放在头文件中共享。 (2) 内联函数应该简洁,只有几个语句,如果语句较多,不适合于定义为内联函数。 (3) 内联函数体中,不能有循环语句、if语句或switch语句,否则,函数定义时即使有inline关键字,编译器也会把该函数作为非内联函数处理。 (4) 内联函数要在函数被调用之前定义。否则,不能起到预期的效果。 2-9 引用引用(reference)是为一个已声明的变量起一个别名。声明一个引用时需要在其名称前加符号“&”,并同时对引用进行初始化,即指定它所引用的对象(是哪一个变量的别名)。声明一个引用一般采用如下格式: & = ;2-10 作用域变量的作用域是指变量可以被引用的区域,变量的作用域决定了变量的可见性。作用域有三种: l 局部作用域 l 全局作用域 l 文件作用域。 具有局部作用域的变量称为局部变量,它们声明在函数(包括main函数)的内部,又称为内部变量。在语句块内声明的变量仅在该语句块内部起作用,也属于局部变量。局部变量的作用域开始于变量声明处,并在标志函数或块结束的右花括号处结束。 例2-21局部变量(包括块内声明的变量)和函数的形参具有局部作用域。 void Myfun(int x)/ 形参x的作用域开始于此 int y = 3;/ 局部变量y的作用域开始于此 int z=x+y;/ 块内局部变量z的作用域开始于此,x和y在该块内可用 / 局部变量k的作用域不包含该块 / 局部变量z的作用域结束 int k; / 局部变量k的作用域开始于此 / 局部变量y、k和形参x的作用域结束全局变量(又称为外部变量)声明在函数的外部,其作用域一般是整个程序源文件。全局作用域范围最广,甚至可以作用于组成该程序的所有源文件。当将多个独立编译的源文件链接成一个程序时,在某个源文件中声明的全局变量,在与该源文件相链接的其它源文件中也可以使用,但使用前必须进行extern外部声明。 例2-22具有全局作用域的全局变量。int x=1;/ 全局变量x的作用域开始于此,结束于整个程序源文件 void Myfun()文件作用域是指在函数外部声明的变量只在当前文件范围内(包括该文件内所有定义的函数)可用,在其它文件中不可用。要使变量具有文件作用域,必须在变量的声明前加上static修饰符。当将多个独立编译的源文件链接成一个程序时,使用static能够避免一个文件的外部变量由于与其它文件中的变量同名而发生冲突。例2-23具有文件作用域的全局变量 static int x = 1;/全局变量x的作用域为当前整个源文件 void Myfun()2-11 生存期,生存期与作用域的关系变量的生存期是指变量的生命周期。变量的作用域是指一个范围,是从代码空间的角度考虑问题。变量的生存期是从时间的角度考虑问题,是指在程序执行的过程中一个变量从创建到被撤消的一段时间。当系统为变量分配内存空间后,变量即开始处于生存期,当变量所占用的内存空间被释放,这个变量即结束了生存期。变量的生存期与作用域是密切相关的,一般变量只有在生存后才能可见(在作用域内)。有些变量(如函数参数)没有生存期,但有作用域,而有时变量虽然在生存期,但却不在作用域内。例2-24 局部变量的生存期和作用域 void Myfun()int x=1;int x(2), y(2);/ 变量“x=1”失去作用域 cout“x=”xn;FuncA();/ 变量x和y在调用函数时失去作用域 第一个声明的局部变量x在语句块内虽然存在,但却是不可见(不可用)的,因为它被语句块内同名的局部变量x所屏蔽了。局部变量x和y在语句块内虽然存在,但在进入函数FuncA()后也是不可见的。2-12 内存分配的方式程序运行时,系统为不同存储属性的变量分配不同类型的内存空间,存储方式决定了变量的作用域和生存期。 变量有以下三种内存分配方式: l 自动分配 l 静态分配 l 动态分配。程序运行后,系统将为程序开辟一块称为栈的活动存储区。自动分配是指在栈中为变量临时分配内存空间。对于自动分配内存的变量,程序运行后,在变量作用域开始时由系统自动为变量分配内存,在作用域结束后即释放内存。一般方式声明的局部变量就是自动分配方式的变量。 系统为每个程序开辟一个固定的静态存储区,静态分配是指在这个固定区域为变量分配内存空间。对于静态分配内存的变量,在编译时就分配了内存地址(相对地址),在程序开始执行时变量就占用内存,直到程序结束时变量才释放内存。全局变量就是静态分配方式的变量。动态分配是指利用一个被称为堆的内存块为变量分配内存空间,堆使用了静态存储区和栈之外的部分内存。动态分配是一种完全由程序本身控制内存的使用的分配方式。对于动态分配内存空间的变量,程序运行后,利用new运算符分配内存,利用delete运算符或程序结束运行释放内存。2-13 存储类型对于非动态分配内存的变量,决定变量采用哪种内存分配方式,是由声明变量时指定的存储类型和变量声明语句的位置所决定的。变量的存储类型有以下四种: l auto自动 l register寄存器 l extern外部 l static静态在声明变量时可以指定变量的存储类型,其一般形式为: ;auto和register用于声明内部变量,auto变量存储在栈中,register变量存储寄存器中。extern用于声明外部变量,static用于声明内部变量或外部变量,extern变量和static变量是存储在静态存储区中。当声明变量时未指定存储类型,则内部变量的存储类型隐含为auto类型,外部变量的存储类型隐含为extern类型。2-14 外部变量的声明方式外部变量的声明分为:l 定义性声明 l 引用性声明 定义性声明表示变量需要分配内存;引用性声明表示要引用的变量已在程序源文件中其它地方进行过定义性声明。定义性声明只能放在函数的外部,引用性声明可放在函数的外部,也可放在函数的内部。extern修饰符主要用于外部变量的引用性声明,外部变量的定义性声明可以不加extern修饰符。进行外部变量的extern引用性声明时一般不能进行初始化,除非定义性声明该外部变量时没有进行初始化。外部变量的使用出现在定义性声明之前需要先进行变量的引用性声明。2-15 在局部变量作用域访问与局部变量同名的全局变量如果局部变量和全局变量同名,在局部作用域内只有局部变量才起作用。C+中可通过使用作用域限定符:来标识同名的全局变量。例2-27#include int amount = 123;/ 全局变量 void main()int amount = 456;/ 局部变量 cout:amount,;/ 输出全局变量 coutamount,;/ 输出局部变量 :amount = 789;/ 访问全局变量 cout:amount,;/ 输出全局变量 coutamountn;/ 输出局部变量 2-16 函数的存储类型函数也具有存储类型,不同存储类型的函数具有不同的作用域。函数被分为内部函数(static)和外部函数(extern,默认值),内部函数只能被同一个源文件中的函数调用,而外部函数可以被其它源文件中的函数调用。调用外部函数前必须先进行外部函数声明。2-17 宏定义2-17-1 设有宏定义如下,变量x的值是多少?# define A 2# define B A+3# define C(x) x*B/2int x=C(2+8);2-18 动态内存分配有时程序只能在运行时才能确定需要多少内存空间来存储数据,这时程序员就需要采用动态内存分配的方法设计程序。动态内存分配是指在程序运行时为程序中的变量分配内存空间,它完全由应用程序自己进行内存的分配和释放。动态内存分配是在一些被称为堆的内存块中为变量分配内存空间。 在C+中最常用的方法是利用new和delete运算符进行动态内存的分配和释放,使用new运算能够检测内存泄漏。运算符new的使用形式:p = new size;l type是数据类型,表示要为哪种数据类型的变量分配空间; l size表示要为多少个变量分配空间,可以省略size(缺省值为1); l p是一个type类型的指针变量,指向所分配的存储单元。 2-19 (引用)给出以下程序的执行结果,并说明为什么是这种结果。#include void fun(int &n)n+;void main()for (int i=0; i3; i+)fun(i);coutiendl;输出结果:132-20 (全局变量)写出下列程序运行后的输出结果。#include int x=1, y=2;int max(int x, int y)return xy ? x : y;void main()int x=3;coutmax1=max(x, y)n;coutmax2=max(:x, y)n;输出结果:max1=3max2=22-21 采用指针方法将一个数组中的所有元素颠倒顺序,结果仍然存放在原来的数组中,要求使用最少的辅助存储单元。2-22 编写一个函数maxmin(),该函数有两个实型参数,执行函数后,第一个参数为两个参数中值较大者,第二个参数为较小者。要求使用引用作为函数参数。第3章 C+面向对象程序设计3-1 对象和类在计算机科学中,对象是系统中用来描述客观事物的一个实体,每一类对象都有自己特定的属性和行为。对象是用于构成系统的一个基本单位,而系统可以看作是由一系列相互作用的对象组成。类是具有相同数据结构(属性)和相同操作功能(行为)的对象的集合,它规定了同类对象的公共属性和行为方法。对象是类的一个实例。3-2 面向对象程序设计方法具有的基本特征面向对象程序设计方法具有四个基本特征:l 抽象:是指对具体问题(对象)进行概括,抽出一类对象的公共属性和行为并加以描述的过程。包括数据抽象和代码抽象(或行为抽象)。l 封装:是将抽象得到的属性数据和行为代码有机地结合,形成一个具有类特征的统一体。通过封装,可以决定对象的哪些属性和行为作为内部细节被隐藏起来,哪些属性和行为是作为对象与外部的接口。封装是实现抽象的基本手段。在C+中,利用类(class)实现对象的抽象和封装。l 继承:是指一个新类可以从现有的类派生而来。新类继承了现有类的特性,包括一些属性和行为,并且可以修改或增加新的属性和行为,使之适合具体的需要。继承很好地解决了软件的可重用性问题。l 多态性:是指类中具有相似功能的不同函数使用同一个名称来实现,并允许不同类的对象对同一消息作出的响应不相同。多态性使程序设计灵活、抽象,具有行为共享和代码共享的优点,很好地解决了程序的函数同名问题。3-3 类的成员的访问控制权限l private属性表示数据成员和成员函数是类的私有成员,它们只允许被本类的成员函数访问或调用;l public属性表示数据成员和成员函数是类的公有成员,它们允许被本类或其它类的成员函数访问或调用,是类的外部接口;l protected属性表示数据成员和成员函数是类的保护成员,它们允许被本类的成员函数和派生类的成员函数访问或调用。3-3-1 假定AA为一个类,a为该类私有的数据成员,GetValue()为该类公有函数成员,它返回a的值,x为该类的一个对象,则访问x对象中数据成员a的格式为:x.GetValue()。3-4 构造函数和析构函数构造函数是一种特殊的成员函数,它是在创建对象时系统自动调用的成员函数。析构函数也是一种特殊的成员函数,它是在对象生存期结束时系统自动调用的成员函数。构造函数的名称与类名相同,析构函数的名称必须在类名前加上“”符号。注意,构造函数和析构函数不能指定任何返回值类型,包括void返回类型。3-4-1 一个类可包含一个析构函数3-4-2 假定一个类AB只含有一个整型数据成员a,当用户不定义任何构造函数时,系统为该类定义的无参构造函数为: AB() 3-5 内联函数成员函数的定义可以放在类体内,这时成员函数将变成内联函数。当成员函数在类的外部定义时,可以在函数头的开始位置加上关键字inline使之成为内联函数。3-6 静态成员变量和静态成员函数以关键字static开头定义的成员变量称为静态变量,它具有全局性。静态数据成员属于整个类,为类的所有对象共享。无论类的对象有多少,类的静态数据成员只有一份,存储在同一个内存空间。即使没有创建类的一个对象,类的静态数据成员也是存在的。使用静态数据成员保证了该数据成员值的唯一性。以关键字static开头定义的成员函数称为静态成员函数。静态成员函数也与一个类相关联,而不只与一个特定的对象相关联。静态成员函数没有this指针,因为类的静态成员函数只有一个运行实例。可以通过对象、类名和作用域限定符、在成员函数中三种方式调用静态成员函数。静态成员函数只能访问类的静态成员(成员变量和成员函数),而不能访问类的非静态成员。因为当通过类名和运算符“:”调用一个静态成员函数时,不能确定函数中所访问的非静态成员属于哪一个对象。3-7 this指针this指针是一个特殊的隐藏在对象中的指针,每一个处于生存期的对象都有一个this指针,用于指向对象本身。当类的某个非静态成员函数被调用时,系统通过this指针确定是哪一个对象的该成员函数被调用。实际上,this指针总是作为一个隐含参数传递给类的每一个成员函数。3-8 友元函数友元类C+提供了一种函数,它虽然不是一个类的成员函数,但可以象成员函数一样访问该类的所有成员,包括私有成员和保护成员。这种函数称为友元(friend)函数。一个函数要成为一个类的友员函数,需要在类的定义中声明该函数,并在函数声明的前面加上关键字friend。友元函数可以是一般函数,也可以是另一个类的成员函数。一个类可以声明另一个类为其友元类,这个友元类的所有成员函数都可以访问声明其为友元的类的所有成员。3-9 类的派生方式派生方式决定了基类的成员在派生类中的访问权限。派生方式共有三种:public、private和protected,缺省为private。为了不破坏基类的封装性,无论采用哪种派生方式,基类的私有成员在派生类中都是不可见的,即不允许在派生类的成员函数中访问基类的私有成员。采用public派生,基类成员的访问权限在派生类中保持不变,即基类所有的公有或保护成员在派生类中仍为公有或保护成员。 可以在派生类的成员函数中访问基类的非私有成员; 可通过派生类的对象直接访问基类的公有成员。采用private私有派生,基类所有的公有和保护成员在派生类中都成为私有成员,只允许在派生类的成员函数中访问基类的非私有成员。采用protected保护派生,基类所有的公有和保护成员在派生类中都成为保护成员,只允许在派生类的成员函数和该派生类的派生类的成员函数中访问基类的非私有成员。 3-9-1 当类的继承方式为私有继承时,基类中的公有成员在派生类中访问权限为private。3-9-2 继承具有传递性,即当基类本身也是某一个类的派生类时,底层的派生类也会自动继承间接基类的成员。3-9-3 多重继承是指派生类具有多个基类。3-10 派生类构造函数和基类构造函数一个派生类对象也属于其基类。在调用派生类的构造函数构建派生类对象时,系统首先调用基类的构造函数构建基类对象。 通过派生类的构造函数调用基类的构造函数有两种方式: 隐式方式是指在派生类的构造函数中不指定对应的基类的构造函数,调用的是基类的默认构造函数(即含有缺省参数值或不带参数的构造函数)。 显式方式是指在派生类的构造函数中指定要调用的基类构造函数,并将派生类构造函数的部分参数值传递给基类构造函数。注意:除非基类有默认的构造函数,否则必须采用显式调用方式 3-10-1 派生类的构造函数的成员初始化列中,能包含:基类的构造函数;派生类中子对象的初始化;派生类中一般数据成员的初始化。3-11 组合类以另一个类的对象作为数据成员,称为组合。3-12 虚基类虚基类并不是一种新的类型的类,而是一种派生方式。采用虚基类方式定义派生类,在创建派生类的对象时,类层次结构中虚基类的成员只出现一次,即基类的一个副本被所有派生类对象所共享。换言之,在多重派生中,要使一个基类在派生类中只有一个拷贝,则必须将这个基类说明为虚基类。采用虚基类方式定义派生类的方法是在基类的前面加上关键字virtual,而定义基类时与一般基类完全一样。 示例:采用virtual虚基类方式定义派生类: class B : virtual public Apublic:int b;class C : virtual public Apublic:int c;使用虚基类派生方式的好处:l 节约内存空间;l 避免在多重派生类中类成员的不明确性。 3-13 多态多态性也是面向对象程序设计方法的一个重要特征,是指属于不同类的对象对同一消息作出不同的响应,具体表现是函数调用的“一种接口、多种方法”。两种多态性:l 编译时多态性:在函数名或运算符相同的情况下,编译器在编译阶段就能够根据函数参数类型或数量的不同来确定要调用的函数 通过重载机制实现。l 运行时多态性:在函数名、函数参数都相同的情况下,只能在程序运行时才能确定要调用的函数 通过虚函数实现。 3-14 重载函数重载(overload):指不同功能代码的函数可以共用一个函数名。C+重载分为函数重载和运算符重载,这两种重载的实质是一样的,因为运算可以理解为调用一个函数。3-15 非成员函数重载运算符和成员函数重载运算符的不同之处。以重载双目运算符为例说明。当利用非成员函数重载双目运算符时,运算符函数的第一个参数代表运算符左边的操作数,运算符函数第二个参数代表运算符右边的操作数。当利用成员函数重载双目运算符时,运算符左边的操作数就是对象本身,不能再将它作为运算符函数的参数,运算符函数只需要一个函数参数。3-15-1 不允许重载的运算符有:*(指针运算符)、:、?:、sizeof3-16 基类指针指向派生类对象C+允许一个基类对象的指针指向其派生类的对象,不允许派生类对象的指针指向其基类的对象将一个基类对象的指针指向其派生类的对象,通过该指针只能访问派生类中从基类继承的公有成员,不能访问派生类自定义的成员,除非通过强制类型转换将基类指针转换为派生类指针3-17 虚函数class Apublic:void Show( ) coutA:Shown; class B : public Apublic:void Show( ) coutShow(); 虽然指针pa指向派生类B的对象b,但调用的还是基类A的成员函数Show(),而不是派生类B的成员函数Show()。 如果想通过基类指针调用派生类中覆盖的成员函数,只有使用虚函数。 虚函数是基类中冠以关键字virtual的成员函数。利用虚函数可以在基类和派生类中使用相同的函数名和参数类型,但定义不同的操作。这样,就为同一个类体系中所有派生类的同一类行为(其实现方法可以不同)提供了一个统一的接口。3-17-1 派生类中对基类的虚函数进行替换时,要求派生类中说明的虚函数与基类中的被替换的虚函数之间满足:与基类的虚函数有相同的名称;与基类的虚函数有相同的参数个数及相同的对应参数类型;与基类的虚函数有相同的返回值。3-18 静态联编和动态联编联编即将函数调用语句与函数代码相关联。两种联编方式: l 静态联编是指编译器在编译阶段就确定了要调用的函数,即早期绑定 l 动态联编是指在程序执行过程中根据具体情况再确定要调用的函数,即后期绑定重载采用静态联编方式:虽然函数名相同,但编译器能够根据函数参数类型的不同确定要调用的函数。重载体现出一种静态多态性或编译时多态性。当通过基类指针调用虚函数时,C+采用动态联编方式。3-19 构造函数、析构函数与虚函数基于构造函数的特点,声明派生类对象时自动调用基类的构造函数,不能将构造函数定义为虚函数。假如使用基类指针指向其派生类的对象,而这个派生类对象是用new运算创建的。当程序使用delete运算撤消派生类对象时,这时只会基类的析构函数,而不会调用派生类的析构函数。如果使用虚析构函数,无论指针所指的对象是基类对象还是派生类对象,程序执行时都会调用对应的析构函数。 3-19-1 写出程序的运行结果:#include iostream.hclass Apublic:A();virtual A()coutA:destructorn;class B:public Apublic:B();B()coutB:destructorn;void main( )A *pA=new B;delete pA;运行结果为:B: destructorA:destructor3-20 抽象基类和纯虚函数不定义具体实现的成员函数称为纯虚函数。纯虚函数的声明:virtual ()= 0 ;抽象类是类的一些行为没有给出具体定义的类。抽象类只能用于类的继承,其本身不能用来创建对象,抽象类又称为抽象基类。抽象基类只提供了一个框架,仅仅起着一个统一接口的作用,而很多具体的功能由派生出来的类去实现。虽然不能声明抽象类的对象,但可以声明指向抽象类的指针。 当基类是抽象类时,只有在派生类中重新定义基类中的所有纯虚函数,该派生类才不会再成为抽象类。 3-21 函数模板函数模板是一种不指定某些参数的数据类型的函数,在函数模板被调用时根据实际参数的类型决定这些函数模板参数的类型。 3-22 类模板类模板是这样一种通用类:在定义类时不说明某些数据成员、成员函数的参数及返回值的数据类型。3-23 写出下列程序运行后的输出结果。如果将A作为B和C的虚基类,程序运行的结果又有何不同#include class Apublic:A(int x)coutA constructor: xendl;A()coutA constructorendl;class B : public Apublic:B(int x, int y) : A(x)coutB constructor: yendl;class C : public Apublic:C(int x, int y) : A(x)coutC constructor: yendl;class D : public C, public Bpublic:D(int x, int y, int z, int w) : B(x, y), C(x, z)coutD constructor: wendl;void main()D obj(1, 2, 3, 4);输出结果:A constructor: 1C constructor: 3A constructor: 1B constructor: 2D constructor: 4将A作为B、C的虚基类的输出结果:A constructorC constructor: 3B constructor: 2D constructor: 43-24 写出下列程序运行后的输出结果,如果使用虚函数,运行结果又如何?#include class Apublic:void Show()coutA:shown;class B : public Apublic:void Show()coutShow();pa = &b; pa-Show();输出结果:A:showA:show使用虚函数的输出结果:A:showB:show3-25 写出下列程序运行后的输出结果。如果使用虚析构函数,运行结果又如何?#include class Apublic:virtual A()coutA:destructorn;class B : public Apublic:B()coutB:destructorn;void main()A* pA = new B;delete pA;输出结果:A:destructor使用虚析构函数的输出结果:B:destructorA:destructor3-26 定义一个抽象类CShape,再利用CShape类分别定义两个派生类CRectangle(表示矩形)和CCircle(表示圆)。三个类都有计算对象面积的成员函数GetArea()和计算对象周长的成员函数GetPerimeter(),在主函数中声明基类指针和派生类对象,并通过基类指针调用不同对象的计算面积和计算周长的成员函数。第4章 创建应用程序框架4-1 MFC应用程序框架和MFC应用程序向导Windows应用程序的类型虽然很多,但同一类型应用程序的结构大致相同,并有很多相同的源代码。因此,可以为同一类型的应用程序设计一个模板,即应用程序框架(Application FrameWorks,AFX)。 应用程序向导(AppWizard)实质上是一个源代码生成器,它所完成的工作包括产生源代码、添加资源和设置编译选项。利用不同的应用程序向导可以自动创建不同类型或风格的应用程序,实现了代码的可重用,减轻了手工编写代码的工作量。4-2 Visual C+中的文件类型后缀类型 说明 dsw 工作区文件 将项目的详细情况组合到工作区中 dsp 项目文件 存储项目的详细情况并替代mak文件 h C+头文件 存储类的定义代码 cpp C+源文件 存储类的成员函数的实现代码 rc 资源脚本文件 存储菜单、工具栏和对话框等资源 rc2 资源文件 用来将资源包含到项目中 ico 图标文件 存储应用程序图标 bmp 位图文件 存储位图 clw 类向导文件 存储ClassWizard类向导使用的类信息 ncb 没有编译的浏览文件 保留ClassView和ClassWizard使用的详细情况 opt 可选项文件 存储自定义的Workspace工作区中的显示情况 4-3 资源标识符的命名规则标识符前缀说明IDR_主菜单、工具栏、应用程序图标和快捷键表IDD_对话框IDC_控件和光标IDS_字符串IDP_信息对话框的字符串ID_菜单命令项4-4 MFC AppWizardexe向导为SDI应用程序创建的几个类MFC AppWizardexe向导在默认方式为SDI应用程序生成了4个类。CMainFrame类是CFrameWnd的派生类,主要负责创建标题栏、菜单栏、工具栏和状态栏。CMysdiDoc类是CDocument的派生类,主要负责应用程序数据的保存和装载,实现文档的序列化功能。CMysdiView类CView的派生类,主要负责客户区文档数据的显示,以及如何进行人机交互。 CMysdiApp类是CWinApp类的派生类,它主要负责完成应用程序的初始化、程序的启动和程序运行结束时的清理工作。4-5 ClassWizard定制现有的类和建立新的类,如把消息映射为类的成员函数,把一个控件与类的成员变量关联起来。用户编程时,利用ClassWizard类向导能够大大简化一些细节问题,如成员变量和成员函数的声明和定义放在何处、成员函数如何与消息映射联系在一起。 利用MFC ClassWizard只能添加MFC类的派生类。若要为项目添加非MFC类的派生类或普通类,执行Insert | New Class命令,打开New Class对话框。在Class type下拉列表框中选择Generic Class选项,在Name文本框中输入类名,在Base class(es)列表框中输入基类名和访问权限。第5章 文档与视图5-1 文档和视图文档(document)是MFC应用程序所处理数据的集合,包括:文本、图形、图像、表格等。一个文档对应于用户当前打开的一个文件。 文档的主要作用是把对数据的处理从用户界面的管理中分离出来,集中处理数据,同时提供与视图交互的接口。 视图(View)是文档在应用程序窗口中的一个映像。视图就像一个观景器,应用程序通过视图向用户显示文档中的数据,并把用户的输入解释为对文档的操作。视图充当了文档与用户之间的媒介物。一个视图总是与一个文档对象相关联,用户通过与文档相关联的视图与文档进行交互。当用户打开一个文档时,应用程序就会创建一个与之相关联的视图。5-2 MFC应用程序中的文档和视图的程序功能及它们之间的关系,文档/视图结构的概念及其主要特点在MFC文档/视图结构中,有关数据处理的工作分为数据的管理和显示两部分: 文档用于管理和维护数据 视图用来显示和编辑数据MFC文档/视图结构应用程序是一个标准的Windows程序,除了具有标准的窗口和界面元素外,还提供一个专门的数据显示区,称为客户区(Client area)。用户对数据的编辑、修改操作都要通过客户区完成,而客户区的管理是由视图负责的,如成员函数OnDraw()负责客户区的显示。 视图是一个没有边框的窗口,它位于主框架窗口中的客户区。视图是文档对外显示的窗口,但它并不能完全独立,它必须依存在一个框架窗口内。一个视图只能拥有一个文档,但一个文档可以同时拥有多个视图。 5-3 文档、视图和应用程序框架之间的相互作用,完成文档和视图之间的相互交互的几个主要的成员函数,刷新视图的几个函数及默认的调用顺序文档、视图和应用程序框架之间包含了一系列复杂的相互作用过程,文档与视图的交互是通过类的公有成员变量和成员函数实现的。一个视图对象有且只有一个与之相关联的文档对象。调用视图类的成员函数GetDocument()可以返回与视图相关联的文档对象的指针,利用这个指针可以访问文档类及其派生类的公有成员变量和成员函数。一个文档对象可以有多个与之相关联的视图对象,但一个文档对象只反映当前视图的变化。当一个文档的数据通过某个视图被修改后,与它关联的每一个视图都必须反映出这些修改。因此,当文档数据发生改变时,必须通知到所有相关联的视图对象,以便更新所显示的数据。 更新与该文档有关的所有视图的方法是调用成员函数CDocument:UpdateAllViews()。程序调用CDocument:UpdateAllViews()函数时,实际上是调用了所有相关视图的OnUpdate()函数,以更新相关的视图。需要时,可以直接在视图派生类的成员函数中调用该函数刷新当前视图。在OnUpdate()中通过调用函数CWnd:Invalidate()刷新整个客户区,我们也可以在自己的CWnd派生类中直接调用函数Invalidate()。 总结:刷新视图时默认的函数调用过程:CDocument:UpdateAllViews()CView:OnUpdate()CWnd:Invalidate()OnPaint()OnDraw()5-4 SDI和MDIMFC基于文档/视图结构的应用程序分为单文档和多文档两种类型,多文档应用程序有一个主窗口,但在主窗口中可以同时打开多个子窗口,每一个子窗口对应一个不同的文档。SDI和MDI使用不同框架窗口。 SDI的框架窗口是唯一的主框架窗口,窗口类是CMainFrame,由CFrameWnd派生而来。 MDI的框架窗口分为主框架窗口和子框架窗口,区别于SDI,MDI的
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 公文最易错别字的
- 饿了外卖市场经理月工作总结
- 如何说课培训课件
- 2026届山东省海阳市美宝学校化学九年级第一学期期中质量跟踪监视试题含解析
- 教学查房的价值与意义
- 2026届贵州省施秉县化学九年级第一学期期末联考试题含解析
- SMT生产现场培训
- 南昌市南大附中2026届英语九上期末调研模拟试题含解析
- 2026届安徽省蚌埠市怀远县化学九年级第一学期期末教学质量检测模拟试题含解析
- 江苏省苏州市虎丘区立达中学2026届化学九年级第一学期期中质量跟踪监视模拟试题含解析
- T-CIRA 41-2022 同位素生产回旋加速器液态靶验收规范
- 伊斯兰教完整版本
- 计量经济学知到智慧树章节测试课后答案2024年秋安徽农业大学
- 《西方的文官制度》教学设计
- 外研版九年级英语上册单元模块满分必刷题 Module 1 【刷中考】(广东专用)(含答案)
- 华为ICT大赛网络赛道考试题库(786题)
- 新能源汽车检测与维修专业调研报告
- 2024年保安员证考试题库及答案(共240题)
- 2018低压电力线高速载波通信互联互通技术规范第3部分:检验方法
- 超声科医院感染管理:培训与演练
- 养老院餐饮供应服务行业发展全景调研与投资趋势预测研究报告
评论
0/150
提交评论