最新C++面试题汇总.doc

上传人:1595****071 文档编号:33806114 上传时间:2022-08-12 格式:DOC 页数:16 大小:183KB
返回 下载 相关 举报
最新C++面试题汇总.doc_第1页
第1页 / 共16页
最新C++面试题汇总.doc_第2页
第2页 / 共16页
点击查看更多>>
资源描述

《最新C++面试题汇总.doc》由会员分享,可在线阅读,更多相关《最新C++面试题汇总.doc(16页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。

1、精品资料C+面试题汇总.C+知识点整理 空指针与野指针的区别:空指针也就是通常指向为NULL的指针,野指针就是指向一块未知的内存区域(可以是通过malloc或new申请空间后,释放后没有将指针置为空),也有可能定义了一个指针没有初始化,由于内存空间中的值在未赋值之前是随机数,所以也有可能诞生野指针。 malloc函数为C语言中的标准函数,标准中规定:在分配内存失败时会返回“NULL Pointer”空指针,而非为初始化的指针。 C+在分配内存失败时会抛出BAD_ALLOC异常。 野指针:指向垃圾内存的指针,而非空指针。 野指针产生原因: 1.声明的指针未被初始化,指针默认值随机产生。创建指针应

2、该将其初始化为NULL或者指向某一内存。 2.free和delete掉的指针未重置为NULL,free后的指针仍指向该内存,但该内存已变为垃圾内存。 另:空指针不指向任何实际的对象或函数,反过来说对象或函数的指针也不可能为空指针。,auto是默认类型,每次调用sum函数时auto类型的变量重新赋值为0,static是静态变量,如果在函数内部进行定义,则只在第一次调用时进行赋初值,其作用范围是sum函数内部,在函数内部可以改静态变量的值;先说宏和函数的区别: 1. 宏做的是简单的字符串替换(注意是字符串的替换,不是其他类型参数的替换),而函数的参数的传递,参数是有数据类型的,可以是各种各样的类型

3、. 2. 宏的参数替换是不经计算而直接处理的,而函数调用是将实参的值传递给形参,既然说是值,自然是计算得来的. 3. 宏在编译之前进行,即先用宏体替换宏名,然后再编译的,而函数显然是编译之后,在执行时,才调用的.因此,宏占用的是编译的时间,而函数占用的是执行时的时间. 4. 宏的参数是不占内存空间的,因为只是做字符串的替换,而函数调用时的参数传递则是具体变量之间的信息传递,形参作为函数的局部变量,显然是占用内存的. 5. 函数的调用是需要付出一定的时空开销的,因为系统在调用函数时,要保留现场,然后转入被调用函数去执行,调用完,再返回主调函数,此时再恢复现场,这些操作,显然在宏中是没有的. 内联

4、函数与宏的区别: 1.内联函数在运行时可调试,而宏定义不可以;2.编译器会对内联函数的参数类型做安全检查或自动类型转换(同普通函数),而宏定义则不会;3.内联函数可以访问类的成员变量,宏定义则不能;4.在类中声明同时定义的成员函数,自动转化为内联函数。external 作用之一: 当它与 “C” 一起连用时,如:extern “C” void fun(int a , int b);会告诉C+编译器在编译fun这个函数名是按着C的规则去翻译相应的函数名而不是C+的,C+的规则在翻译这个函数名时会把fun这个名字变得面目全非。回调函数就是一个通过函数指针调用的函数。 如果你把函数的指针(地址)作为

5、参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。 回调函数不是由该函数的实现方法直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应回调函数不能是特定的类成员函数。因为类成员函数含有this指针。核心就是类成员函数需要this指针访问函数,而全局或者静态函数不需要this指针。 简言之,类的成员函数需要隐含的this指针而回调函数没有办法提供。 int *a34, 则变量占有的内存空间为每个元素存放的都是二级指针,每个指针在32位系统下占4个字节的内存,共3*4=12个元素,则共占内存12*4=48字节C+中使用模板类的原因:

6、(1) 可用来创建动态增长和减小的数据结构; (2) 它是类型无关的,因此具有很高的可利用性; (3) 它在编译时检查数据类型,保证了类型安全; (4) 它是平台无关的,具有可移植性; (5) 可用于基本数据类型。 A. 由于编译后的名字不同,C+程序不能直接调用C 函数B. extern C 既可以修饰函数也可以修饰变量C. c+提供关键字extern“C”,被extern C修饰的是按照C语言方式编译和连接的它是if not define 的简写,是宏定义的一种,实际上确切的说,这应该是预处理功能三种(宏定义、文件包含、条件编译)中的一种-条件编译。 在c语言中,对同一个变量或者函数进行多

7、次声明是不会报错的。所以如果h文件里只是进行了声明工作,即使不使用# ifndef宏定义,多个c文件包含同一个h文件也不会报错。 但是在c+语言中,#ifdef的作用域只是在单个文件中。所以如果h文件里定义了全局变量,即使采用#ifdef宏定义,多个c文件包含同一个h文件还是会出现全局变量重定义的错误。 使用#ifndef可以避免下面这种错误:如果在h文件中定义了全局变量,一个c文件包含同一个h文件多次,如果不加#ifndef宏定义,会出现变量重复定义的错误;如果加了#ifndef,则不会出现这种错误。 根据语言定义, 在指针上下文中的常数0 会在编译时转换为空指针。也就是说, 在初始化、赋值

8、或比较的时候,如果一边是指针类型的值或表达式, 编译器可以确定另一边的常数0 为空指针并生成正确的空指针值。因此下边的代码段完全合法:char *p = 0;if(p != 0) 然而, 传入函数的参数不一定被当作指针环境, 因而编译器可能不能识别未加修饰的0 “表示” 指针。在函数调用的上下文中生成空指针需要明确的类型转换,强制把0 看作指针。例如, Unix 系统调用execl 接受变长的以空指针结束的字符指针参数。它应该如下正确调用:execl(/bin/sh, sh, -c, date, (char *)0);如果省略最后一个参数的(char *) 转换, 则编译器无从知道这是一个空指

9、针,从而当作一个0 传入。(注意很多Unix 手册在这个例子上都弄错了。) 堆和栈A. 堆的大小仅受操作系统的限制,栈的大小一般一般较小B. 在堆上频繁的调用new/delete容易产生内存碎片,栈没有这个问题A. 堆和栈都可以动态分配所谓动态内存分配就是指在程序运行的过程中动态地分配或者回收存储空间的分配内存的方法。动态内存分配不象数组等静态内存分配方法那样需要预先分配存储空间,而是由系统根据程序的需要即时分配,且分配的大小就是程序要求的大小。从以上动、静态内存分配比较可以知道动态内存分配相对于静态内存分配的特点: 1、不需要预先分配存储空间; 2、分配的空间可以根据程序的需要扩大或缩小。

10、一是时间不同。静态分配发生在程序编译和连接的时候。动态分配则发生在程序调入和执行的时候。 二是空间不同。堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由函数alloca()进行分配。不过栈的动态分配和堆不同,他的动态分配是由编译器进行释放,无需我们手工实现。对于一个进程的内存空间而言,可以在逻辑上分成3个部份:代码区,静态数据区和动态数据区。动态数据区一般就是“堆栈”。“栈(stack)”和“堆(heap)”是两种不同的动态数据区,栈是一种线性结构,堆是一种链式结构。进程的每个线程都有私有的“栈”,所以每个线程虽然

11、代码一样,但本地变量的数据都是互不干扰。一个堆栈可以通过“基地址”和“栈顶”地址来描述。全局变量和静态变量分配在静态数据区,本地变量分配在动态数据区,即堆栈中。程序通过堆栈的基地址和偏移量来访问本地变量。 一般,用static修饰的变量,全局变量位于静态数据区。函数调用过程中的参数,返回地址,EBP和局部变量都采用栈的方式存放。 内存管理常用区间和区间中的数据静态区(static): 存放(初始化的)全局变量、静态变量和(未初始化的)全局变量和静态变量; 栈区(stack): 存放局部变量和函数的形参。栈中的内存空间由编译器自动申请和释放。 堆区(heap): 存放动态分配内存函数申请的变量。

12、堆中的内存空间需要程序员手动释放,否则会引发内存泄露。 5. 分配效率:栈的效率比较高。堆的效率比栈要低得多。 6. 增长方向:堆的增长方向是从程序低地址到高地址向上增长,而栈的增长方向刚好相反(实际情况可能不是这样的,与CPU的体系结构有关) 堆是不连续的,生长方向是向上的,即向着内存地址增大的方向增长;栈是连续的,生长方向是向下的,即向着内存地址减小的方向增长。栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在WINDOWS下,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间

13、超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小。 堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。阐述 C+ STL 中 vector, set, multiset , list, map, multimap , deque 的特点 .vector和built-in数组类似,它拥有一段连续的内存空间,并且起始地址不变,因此它能非常好的支持随即存取,即操作符,但由于它的内存空间是连续的,所以在中间进行插入和删除会造成内存块的拷贝,另外,当该数组后的内存空间不够时,需要重新申

14、请一块足够大的内存并进行内存的拷贝。这些都大大影响了vector的效率。list就是中的双向链表(根据sgi stl源代码),因此它的内存空间可以是不连续的,通过指针来进行数据的访问,这个特点使得它的随即存取变的非常没有效率,因此它没有提供操作符的重载。但由于链表的特点,它可以以很好的效率支持任意地方的删除和插入。deque是一个double-ended queue,它的具体实现不太清楚,但知道它具有以下两个特点:它支持操作符,也就是支持随即存取,并且和vector的效率相差无几,它支持在两端的操作:push_back,push_front,pop_back,pop_front等,并且在两端操

15、作上与list的效率也差不多。Map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据处理能力,由于这个特性map内部的实现自建一颗红黑树(一种非严格意义上的平衡二叉树),这颗树具有对数据自动排序的功能。set是集合,set中不会包含重复的元素,这是和vector的第一个区别,第二个区别是set内部用平衡二叉树实现,便于元素查找,而vector是使用连续内存存储,便于随机存取。因此在实际使用时,如何选择这几个容器中哪一个,应根据你的需要而定,一般应遵循下面的原则:1、如果你需要高效的随即存取,而不在乎插入和删除的

16、效率,使用vector2、如果你需要大量的插入和删除,而不关心随即存取,则应使用list3、如果你需要随即存取,而且关心两端数据的插入和删除,则应使用deque。4、如果你要存储一个数据字典,并要求方便地根据key找value,那么map是较好的选择5、如果你要查找一个元素是否在某集合内存中,则使用set存储这个集合比较好 vector, 译为 “向量”, 可以理解为 线性代数 中的向量,也可以理解为动态数组。为了实现动态,有的编译器会默认为vector生成一个长度,当插入的元素的个数大于该长度时,就会生成一个长度为原长度二倍的数组,并将原来数组的数据拷贝在新数组中。 插入操作的平均复杂度为O

17、(1). 因此,插入操作有可能使前面获取的迭代器失效。 deque, 有双向(de)队列(queue)的意味,是可实现双向插入数据的动态数组。为了实现双向插入的功能,编译器一般会把其数据结构设置成一段一段的数组,每段数组链接起来构成一个超级大链表,然后为之重载数组的接口。如果前面的数组填满了,就会在大链表的前面生成一段数组,如果后面的数组填满了,也一样。因此,插入操作一般不会影响前面获取的迭代器。 list: 双向链表。有的编译器底层用环形链表来实现的。插入操作一般不会影响已获取的迭代器。 set, multiset: 分别实现的是无重复元素的集合和有重复元素的集合。一般由红黑树实现 map,

18、multimap: 分别实现的是无重复元素的映射关系,和有重复元素的映射关系。一般由红黑树实现。 进程和线程1.定义进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位.线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.2.关系一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行.相对进程而言,线程是一个更加接近于执行体的概念,它

19、可以与同进程中的其他线程共享数据,但拥有自己的栈空间,拥有独立的执行序列。3.区别进程和线程的主要差别在于它们是不同的资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。1)简而言之,一个程序至少有一个进程,一个进程至少有一个线程.2)线程的划分尺度小于进程,使得多线程程序的并

20、发性高。3)另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。4)线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。5)从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。4.优缺点线程和进程在使用上各有优缺点:线程执行开销小,但不利于资源的管理和保护;而进程正相反。同时,线程适合于在SMP机器

21、上运行,而进程则可以跨机器迁移。并行计算机中的并行,指的是同时存在于内存中的多道作业都处于运行状态。实际上都是宏观上并行,微观上串行,因为这些作业都是开始各自的运行,但都没运行完毕,只是交替地使用cpu。在操作系统中是指,一组程序按独立异步的速度执行,不等于时间上的重叠(同一个时刻发生)。要区别并发。并发是指:在同一个时间段内,两个或多个程序执行,有时间上的重叠(宏观上是同时,微观上仍是顺序执行)。并行也指8位数据同时通过并行线进行传送,这样数据传送速度大大提高,但并行传送的线路长度受到限制,因为长度增加,干扰就会增加,数据也就容易出错。并发在中,是指一个时间段中有几个程序都处于已启动运行到运

22、行完毕之间,且这几个程序都是在同一个上运行,但任一个时刻点上只有一个程序在处理机上运行。在关系中,允许多个用户同时访问和更改共享数据的进程。SQL Server 使用锁定以允许多个用户同时访问和更改共享数据而彼此之间不发生冲突。操作系统并发程序执行的特点:并发环境下,由于程序的封闭性被打破,出现了新的特点:程序与计算不再一一对应,一个程序副本可以有多个计算并发程序之间有相互制约关系,直接制约体现为一个程序需要另一个程序的计算结果,间接制约体现为多个程序竞争某一资源,如处理机、等。并发程序在执行中是走走停停,断续推进的。并发和并行的区别和联系“并行”是指无论从微观还是宏观,二者都是一起执行的,就

23、好像两个人各拿一把铁锨在挖坑,一小时后,每人一个大坑。 而“并发”在微观上不是同时执行的,只是把时间分成若干段,使多个进程快速交替的执行,从宏观外来看,好像是这些进程都在执行,这就好像两个人用同一把铁锨,轮流挖坑,一小时后,两个人各挖一个小一点的坑,要想挖两个大一点得坑,一定会用两个小时。 从以上本质不难看出,“并发”执行,在多个进程存在资源冲突时,并没有从根本提高执行效率并发,是在同一个cpu上同时(不是真正的同时,而是看来是同时,因为cpu要在多个程序间切换)运行多个程序。并行,是每个cpu运行一个程序。打个比方,并发,就像一个人(cpu)喂2个孩子(程序),轮换着每人喂一口,表面上两个孩

24、子都在吃饭。并行,就是2个人喂2个孩子,两个孩子也同时在吃饭。并发和并行是即相似又有区别的两个概念,并行是指两个或者多个事件在同一时刻发生;而并发是指两个或多个事件在同一时间间隔内发生。在多道程序环境下,并发性是指在一段时间内宏观上有多个程序在同时运行,但在中,每一时刻却仅能有一道程序执行,故微观上这些程序只能是分时地交替执行。倘若在中有多个处理机,则这些可以并发执行的程序便可被分配到多个处理机上,实现并行执行,即利用每个处理机来处理一个可并发执行的程序,这样,多个程序便可以同时执行。同步同步就是协同步调,按预定的先后次序进行运行。如:你说完,我再说。“同”字从字面上容易理解为一起动作。其实不

25、是,“同”字应是指协同、协助、互相配合。如进程、线程同步,可理解为进程或线程A和B一块配合,A执行到一定程度时要依靠B的某个结果,于是停下来,示意B运行;B依言执行,再将结果给A;A再继续操作。互斥两个或两个以上的进程,不能同时进入关于同一组共享变量的临界区域,否则可能发生与时间有关的错误,这种现象被称作进程互斥.链地址法:将哈希值相同的元素用链表进行相连 线性探测再散列法:冲突后依次向下循环查找空位进行放置 BC为哈希值构造方法,并非解决冲突方法 哈希函数的构造方法:数字分析法 平方取中法 除留取余法 分段叠加法 处理冲突的方法:开放地址法(包括线性探测法、二次探测法、伪随机探测法) 链地址

26、法 树转换为二叉树1)加线。在所有兄弟结点之间加一条连线。(2)去线。树中的每个结点,只保留它与第一个孩子结点的连线,删除它与其它孩子结点之间的连线。(3)层次调整。以树的根节点为轴心,将整棵树顺时针旋转一定角度,使之结构层次分明。(注意第一个孩子是结点的左孩子,兄弟转换过来的孩子是结点的右孩子森林转换为二叉树(1)把每棵树转换为二叉树。(2)第一棵二叉树不动,从第二棵二叉树开始,依次把后一棵二叉树的根结点作为前一棵二叉树的根结点的右孩子,用线连接起来。二叉树转换为树是树转换为二叉树的逆过程。(1)加线。若某结点X的左孩子结点存在,则将这个左孩子的右孩子结点、右孩子的右孩子结点、右孩子的右孩子

27、的右孩子结点,都作为结点X的孩子。将结点X与这些右孩子结点用线连接起来。(2)去线。删除原二叉树中所有结点与其右孩子结点的连线。(3)层次调整。二叉排序树又称“二叉查找树”、“二叉搜索树”。二叉排序树:或者是一棵空树,或者是具有下列性质的二叉树:1. 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;2. 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;3. 它的左、右子树也分别为二叉排序树。二叉排序树通常采用二叉链表作为存储结构。中序遍历二叉排序树可得到一个依据关键字的有序序列,一个无序序列可以通过构造一棵二叉排序树变成一个有序序列,构造树的过程即是对无序序列进行排

28、序的过程。每次插入的新的结点都是二叉排序树上新的叶子结点,在进行插入操作时,不必移动其它结点,只需改动某个结点的指针,由空变为非空即可。搜索、插入、删除的时间复杂度等于树高,期望O(logn),最坏O(n)(数列有序,树退化成线性表,如右斜树)。虽然二叉排序树的最坏效率是O(n),但它支持动态查找,且有很多改进版的二叉排序树可以使树高为O(logn),如AVL、红黑树等。二元排序树的查找算法在二元排序树b中查找x的过程为:1.若b是空树,则搜索失败,否则:2.若x等于b的根节点的数据域之值,则查找成功;否则:3.若x小于b的根节点的数据域之值,则搜索左子树;否则:4.查找右子树。二叉排序树的删

29、除算法在二叉排序树中删去一个结点,分三种情况讨论:1.若*p结点为叶子结点,即PL(左子树)和PR(右子树)均为空树。由于删去叶子结点不破坏整棵树的结构,则只需修改其双亲结点的指针即可。2.若*p结点只有左子树PL或右子树PR,此时只要令PL或PR直接成为其双亲结点*f的左子树(当*p是左子树)或右子树(当*p是右子树)即可,作此修改也不破坏二叉排序树的特性。3.若*p结点的左子树和右子树均不空。在删去*p之后,为保持其它元素之间的相对位置不变,可按中序遍历保持有序进行调整。比较好的做法是,找到*p的直接前驱(或直接后继)*s,用*s来替换结点*p,然后再删除结点*s。一、原反补码1.设X=2

30、1X=+0010101Y=-0010101原码:正数的原码:符号为0,数值部分不变X原=00010101负数的原码:符号为1,数值部分不变Y原=10010101反码:正数的反码等于原码X反=00010101负数的反码:符号为1,数值部分按位取反Y反=11101010补码:正数的补码等于原码X补=00010101 负数的补码:符号为1,数值部分按位取反,末位加1负数的补码等它的反码加1Y补=111010112.和的补码等于补码的和差的补码等于被减数的补码加上减数取负后的补码移码(增码)是机器数的另一种表示方法,最适合表示浮点数的阶码3.定点整数的取值范围原反码-(2n-1-1)到2n-1-1补移

31、码-2n-1到2n-1-11、 谈谈你对面向对象编程的认识面向对象编程强调抽象、封装、继承、多态抽象:我们在定义一个抽象类的时候,实际上就是把一类事物共有的属性和行为提取出来,形成一个物理模型(模版),这种研究问题的方法称为抽象。你可以这样来想,抽象就是一个类的最基础的东西,比方说人,他的抽象类可能就是都从母体出来,有皮肤。但具体到你是黑人,白人,还得黑人类,白人类来说明 。封装:就是将类的属性包装起来,不让外界轻易的知道他的内部实现。只提供给你对外的接口让你来调用。好处可以增强模块的独立性。如设置属性或方法的访问权限(private、protected、public、默认)。继承:就是从父类

32、把它的有用的东西拿过来自己用,不用在自己去实现了,像母亲会把双眼皮传给女儿,不用她自己去割了 。多态:一个对象变量可以指向多种实际类型的现象。一个人,在不同场合下,有不同的身份,不同的状态。比如在家里,你是父母的孩子;在学校,你就是学生;在公司,你就是老板的职员。再比如在接口总定义一个run()方法,是什么在跑,汽车还是马?通过不同类的实现来表示相似的逻辑。顺便说一下重载和重写(覆盖)的区别:重载:相同的方法名,不同的实现机制(通过传入不同个数或类型的参数)。当程序运行过程中自己去判断到底该调用谁。比方说打人,那么多人,当你打起群架来,该打谁就打谁,事前你也不知道。重写:从父类继承而来的方法不

33、能满足需要的情况下,可以将此方法的逻辑在子类中重新实现。我们最常用的就是重写toString()方法了。面向对象可以理解成对待每一个问题,都是首先要确定这个问题由几个部分组成,而每一个部分其实就是一个对象。然后再分别设计这些对象,最后得到整个程序。传统的程序设计多是基于功能的思想来进行考虑和设计的,而面向对象的程序设计则是基于对象的角度来考虑问题。这样做能够使得程序更加简洁、清晰。:面向过程和面向对象有什么区别?面向过程就是指分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。面向对象是把构成问题的事务分解成各个对象,建立对象的目的不是为了完成一个

34、步骤,而是为了描叙某个事物在整个解决问题步骤中的行为。面向对象面向的是,面向过程面向的是。虽然面向对象在数据构造方面优于面向过程,但是面向过程是算法设计的实现基础,面向对象的程序设计最终还要转化为面向过程。面向对象程序设计的基本概念:面向对象, 概括地说, 就是把问题抽象为对象, 设置属性(数据) , 指定事件或处理方式(代码) 来达到目的, 强调从问题域的概念到软件程序和界面的直接映射。面向对象程序设计中的概念主要包括:对象、类、数据抽象、继承、动态绑定、数据封装、多态性、消息传递。通过这些概念面向对象的思想得到了具体的体现。 面向对象程序设计的基本特征:1)对象:对象是运行期的基本实体,它

35、是一个封装了数据和操作这些数据的代码的逻辑实体。2)类:类是具有相同类型的对象的抽象。一个对象所包含的所有数据和代码可以通过类来构造。3)封装性:封装是一种信息隐蔽技术,它体现于类的说明,是对象的重要特性。封装使数据和加工该数据的方法(函数)封装为一个整体,以实现独立性很强的模块,使得用户只能见到对象的外特性(对象能接受哪些消息,具有那些处理能力),而对象的内特性(保存内部状态的私有数据和实现加工能力的算法)对用户是隐蔽的。封装的目的在于把对象的设计者和对象者的使用分开,使用者不必知晓行为实现的细节,只须用设计者提供的消息来访问该对象。4)继承性:继承性是子类自动共享父类之间数据和方法的机制。

36、它由类的派生功能体现。一个类直接继承其它类的全部描述,同时可修改和扩充。继承具有传递性。继承分为单继承(一个子类只有一父类)和多重继承(一个类有多个父类)。类的对象是各自封闭的,如果没继承性机制,则类对象中数据、方法就会出现大量重复。继承不仅支持系统的可重用性,而且还促进系统的可扩充性。5)多态性:对象根据所接收的消息而做出动作。同一消息为不同的对象接受时可产生完全不同的行动,这种现象称为多态性。利用多态性用户可发送一个通用的信息,而将所有的实现细节都留给接受消息的对象自行决定,如是,同一消息即可调用不同的方法。例如:Print消息被发送给一图或表时调用的打印方法与将同样的Print消息发送给

37、一正文文件而调用的打印方法会完全不同。多态性的实现受到继承性的支持,利用类继承的层次关系,把具有通用功能的协议存放在类层次中尽可能高的地方,而将实现这一功能的不同方法置于较低层次,这样,在这些低层次上生成的对象就能给通用消息以不同的响应。在OOPL中可通过在派生类中重定义基类函数(定义为重载函数或虚函数)来实现多态性。6)动态绑定:绑定指的是将一个过程调用与相应代码链接起来的行为。动态绑定是指与给定的过程调用相关联的代码只有在运行期才可知的一种绑定,它是多态实现的具体形式。7)消息传递:对象之间需要相互沟通,沟通的途径就是对象之间收发信息。消息内容包括接收消息的对象的标识,需要调用的函数的标识

38、,以及必要的信息。消息传递的概念使得对现实世界的描述更容易。1、C 和 C+怎样分配和释放内存,区别是什么在C+中,内存分成5个区,他们分别是堆、栈、自由存储区、全局/静态存储区和常量存储区。申请和释放堆中分配的存储空间,分别使用new 和 delete 的两个运算符来完成:malloc与free是C+/的标准库函数,new/delete是C+的运算符。它们都可以用于申请动态内存和释放内存。对于非内部数据类型对象而言,光用malloc/free无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free.

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 教育专区 > 小学资料

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号© 2020-2023 www.taowenge.com 淘文阁