程序设计基础

UML的特点:

  1. 统一了面向对象方法的有关概念和描述方法;
  2. 表达能力强,能对各种并发式系统进行建模,提供了一种扩展机制;
  3. 是一种标准的建模语言。

 

 

  • 父类写了一个virtual函数,子类空间继承并覆盖该函数时不写virtual也能实现多态。virtual修饰符能被隐形地继承,virtual可加可不加。子类空间有父类空间的所有变量(static除外),同一个函数只能存在一个实体(inline除外)。子类空间有父类的私有变量,私有变量不能直接访问。

 

引用与指针的区别

  1. 引用必须初始化,指针不需要。
  2. 引用初始化之后不能被改变,指针可以改变所指的对象。
  3. 不存在指向空的引用,但存在指向空的指针。

 

  • 当数组名作为参数时传递的是地址,而其他类型如int作为参数时行传递的时,系统会为其开辟空间存储参数相当于传递的是函数参数值的拷贝,被调函数内部形参的改变并不会影响实参的值。

 

重载与覆盖的区别

重载要求函数名相同,但是参数列表不同,返回值可以相同也可以不同

覆盖要求函数名参数列表和返回值都必须相同

在类中重载是一个类中多个成员函数的关系,而覆盖是基类和子类之间的成员函数的关系

重载函数的调用根据参数的类型来决定调用哪一个函数,覆盖函数的调用则根据对象的类型来决定调用哪一个函数。

在类中对成员函数重载不能实现多态

 

什么是多态?

同一操作作用与不同的对象,可以有不同的解释,产生不同的结果这就是多态。简单的说就是基类的引用指向子类的对象

 

内存分配的方式?

  1. 从静态区域进行分配,内存在系统编译过程时就已经分配完成,这块内存在系统整个运行期间都存在。如全局变量。
  2. 在栈上创建,在执行函数时,函数内局部变量的存储单元可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配的运算内置于处理器的指令集中,效率高,但分配的内存空间有限。
  3. 从堆上分配又称动态内存分配,程序在运行时用malloc或new申请任意大小的内存,由程序员决定何时使用free或delete释放内存。动态内存生存期由程序员决定,使用灵活,但问题也最多。

 

const与#define的比较

  1. const常量有数据类型而宏常量没有数据类型。编译器可以对前者进行安全检查,而对后者只进行字符替换没有类型安全检查,在字符替换期间会产生意料不到的结果(边际效应)
  2. 有些集成化的调试工具可以对const进行调试,但不能对宏常量进行调试。

 

C和C++区别?

从机制上看,C是面向过程的语言,C++是面向对象的语言,提供了类。

从适用方面,C语言更适合代码体积小,效率高的场合,如嵌入式。C++更适合上层的复杂的场合。linux核心大多是C语言写的,因为它是系统软件,要求效率极高。

C++是C的超集,它扩充了C语言。

C语言是结构化编程语言,C++是面向对象编程语言。C++侧重于类的设计而不是逻辑设计,它侧重于对象而不是过程。

 

为什么要用多态?多态有什么好处?

我们知道封装可以隐藏代码实现的细节,实现代码的模块化;继承可以扩展代码模块(类),实现代码的重用。

多态除了实现代码的复用外,还可以解决项目中紧耦合度问题,提高程序的可扩展性。耦合度是模块与模块之间代码的关联程度,通过对系统分析分成一个一个的子模块,子模块提供稳定的接口,达到降低系统耦合度的目的,模块与模块之间尽量使用接口进行访问而不是随意的引用其他模块的成员变量。

好处:应用程序不必为派生类编写功能调用,只要对抽象的基类进行处理即可,大大提高了程序的可复用性。(指向基类的指针调用派生类的方法)。

派生类的功能可以通过基类的方法或引用变量所调用,这叫向后兼容,可以提高扩充性和可维护性。

 

C++值传递的方式:值传递,引用传递,指针传递

 

指针和引用作为函数参数传递的区别?

指针作为参数进行传递:传递给形参的是实参的地址,因此对形参的改变会导致实参的变化。

将引用作为函数的参数进行传递开辟的堆栈空间存储的是实参的地址,被调函数对形参的处理相当于间接寻址,形参的改变会引起实参的改变。引用传递方式是在函数定义时在形参前面加上引用运算符“&”。使得函数调用方便自然,不仅能节约时间还能节约空间。

值传递(passl-by-value)过程中,被调函数的形式参数作为被调函数的局部变量处理,即在堆栈中开辟了内存空间以存放由主调函数放进来的实参的值,从而成为了实参的一个副本。值传递的特点是被调函数对形式参数的任何操作都是作为局部变量进行,不会影响主调函数的实参变量的值。

 

将引用作为参数有哪些特点

传递引用给函数与传递指针的效果是一样的,被调函数的形参相当于被当成主调函数实参的一个别名来使用,对形参的任何操作都相当于对主调函数中实参的操作。

使用引用传递函数的参数,不会在内存中产生实参的副本,它是直接对实参进行操作,而使用一般变量进行函数参数传递时,发生函数调用需要给形参分配存储单元,形参的变量是实参的副本;如果传递的是对象,还得调用拷贝构造函数。因此当参数较大时用引用传递比一般的变量传递效率高占空间少。

使用指针作为函数的参数也能达到引用作为参数传递的的效果,但指针作为函数的参数在被调函数中需要给形参分配存储单元,且需要重复使用*指针变量名进行使用,程序的阅读性差,容易产生错误,在主调函数的参数调用点处必须使用变量的地址作为实参。相对来说引用更容易使用,更清晰。

 

全局变量与局部变量的区别?

生命周期不同:全局变量随主程序的创建而创建,跟随着整个程序的生命周期,随主程序的销毁而销毁。

局部变量在局部函数内部,退出函数就不存在。

通过声明后,全局变量在程序的各部分都可以用到,局部变量只能在局部函数中使用;操作系统和编译器通过内存分配的位置来区分全局变量和局部变量,全局变量分配在全局数据段在程序开始运行时加载,局部变量分配在堆栈里。

 

堆与栈的区别?

栈的空间由程序自动分配与释放,堆是由程序员分配与释放。

程序在编译时进行的函数与变量的存储是在栈上进行的,运行过程中对函数的调用参数的传递也是在栈上进行。

栈的存储空间有限,堆的存储空间自由灵活。

 

面向对象的三个基本特征?

封装:将客观的事物抽象成类,对类中的方法和变量进行保护不对外公开,即隐藏对象的属性和实现的细节,只对外部提供接口,控制程序中属性的读和修改的 访问级别。

继承:面向对象的一大特性就是程序的复用性,子对象能够使用父对象的方法和属性,并且能对父类进行功能的扩充。实现继承,接口继承。

多态:即接口的不同实现方式,将父对象设置成为一个或多个子对象相等的技术,根据传给父对象的变量作用在不同的子对象产生的不同结果。简单的说是允许子类型的指针赋值给父类型的指针。

 

可复用的软件元素:项目计划,成本估计,体系结构,需求模型,规格说明和设计,用户文档和技术文档,用户界面,数据结构和测试用例。

 

举例3个查找算法?

二分查找:要求带查找序列有序。

哈希查找:若能处理好位置冲突的情况下查找性能好,主要是哈希函数的选择。

二叉排序树:若树比较平衡的情况下查找性能好。

 

Java和C的区别

1)内存管理

在Java中,基本不用考虑内存的问题,如果想用一个对象,new一个就可以,这个过程的背后则是JRE为对象分类的一定内存,当JRE发现你不再使用这个对象的时候,他就会自动回收内存,也就是说只管借东西,不用管归还

但是C则不同,如果你想用,你可以用malloc之类的方法申请内存,当你使用完了,需要自己把这块内存归还回去,也就是调用free方法来完成这个任务。由于需要显式的归还内存,因此当一个函数需要将一块内存返回给调用者的时候,问题就比较复杂了,不如面向对象和具有内存回收功能的Java那么直观了。

2)面向对象

Java的面向对象的特点很明显,而C则是一个地道的结构化语言。 Java中有一个字符串类String, 通过调用 String.length()就可以知道字符串的长度,但是在C语言中,则需要调用函数strlen(str)来得到字符串(字符数组)的长度。由于C不是面向对象的语言,也就没有this的概念,因此当使用一个与某个“东西”相关的函数时,就需要不厌其烦的将代表这个“东西”的变量作为参数传递进去。

3)Java里面没有指针,不支持全局变量和结构体

 

什么是预处理

程序设计中的预处理(Preprocess)是在程序源代码被编译之前,由预处理器(Preprocessor)对程序源代码进行的处理。这个过程并不对程序的源代码进行解析,但它把源代码分割或处理成为特定的符号用来支持宏调用。

预处理器的主要作用就是把通过预处理的内建功能对一个资源进行等价替换,最常见的预处理有:文件包含,条件编译、布局控制和宏替换4种。

 

软件的生命周期:

可行性研究→需求分析→软件设计(概要设计和详细设计)→编码→软件测试→软件维护

 

JAVA的特点:

面向对象

分布式:JAVA包括一个支持HTTP和FTP等基于TCP/IP的协议的子库。因此,JAVA应用程序可以凭借URL打开并访问网络上的对象。

可移植的最大功臣是JVM的技术。大多数编译器产生的目标代码只能运行在一种CPU上(如Intel的x86系列) 但JAVA编译器就不同了。JAVA编译器产生的目标代码(J-Code) 是针对一种并不存在的CPU--JAVA虚拟机(JAVA Virtual Machine),而不是某一实际的CPU。JAVA虚拟机能掩盖不同CPU之间的差别,同体系结构无关的特性使得Java应用程序可以在配备了Java解释器和运行环境的任何计算机系统上运行

多线程 多线程功能使得在一个程序里可同时执行多个小任务

Java使用Unicode作为它的标准字符,这项特性使得Java的程序能在不同语言的平台上都能撰写和执行

 

软件过程模型:

瀑布模型:把软件开发过程分为若干阶段,每个阶段任务相对独立,在软件的生存期的每个阶段都采取科学的管理技术和良好的方法与技术,而且在每个阶段完成前都从技术和管理两个角度进行严格的审查,经确认之后才开始下一阶段。是一种线性开发模型具有不可回溯性,适用于需求变化少,开发人员能一次性获得所有需求的开发。

优点:模型简单,执行容易

缺点:不能适应变更

快速原型:快速建立一个能反映用户主要需求的原型系统,让用户在计算机上试用它,用户在试用后提出修改意见,开发人员根据修改意见快速修改原型系统,知道满足用户要求,适用于已有产品或产品原型(样品),只需客户化的工程项目。

增量模型:开发人员将软件系统模块化,将每个模块作为一个增量组件,从而分批次地分析,设计编码和测试这些增量组件。开发人员不需要一次性提交软件产品给用户,而是分批次地提交是一种递增式的过程。

优点:降低了软件开发的风险,开发顺序灵活。

螺旋模型:兼顾了快速原型的迭代特征以及瀑布模型的系统化与严格监控,强调了其他模型所忽视的风险分析。螺旋模型采用了一种周期性的方法进行系统开发,在每个项目阶段采用瀑布模型,这种模型每一个周期都包括了需求定义,风险分析,工程实现和评审4个阶段,由这4个阶段进行迭代。软件开发没迭代一次就又前进一个层次。使用于风向较大的大型软件项目开发。

 

机器语言:是纯粹的二进制数据表示的语言,能被计算机直接识别的语言。汇编语言和高级语言经过编译连接最终形成能被CPU识别和运行的机器语言。

汇编语言:是以人们较熟悉的语句直接表示CPU动作的语言,汇编语言通常与机器语言对应,与具体的计算机相关属于低级语言。直接对硬件产生作用,程序的执行效率高,它比机器语言直观,易阅读和排错。

高级语言:以“人”的思维来描述电脑运行的语言,完全脱离了CPU“思维”模式,简单,易于理解,可移植性高,相对汇编语言程序的执行效率低。

 

编译器:把源程序的所有指令都翻译成机器语言,并保存为二进制文件,计算机可以直接以机器语言运行程序,速度快。

解释器:在程序执行时把每一条语句翻译成机器语言给计算机执行,运行速度慢。

 

模块化程序设计的意义?

模块化程序设计的基本思想是自顶向下,逐步分解,分而治之,即将一个较大的程序按照功能分解为多个较小的模块,各模块相对独立,功能单一,结构清晰,接口简单。

降低了程序的复杂度,使程序设计,调试和维护等操作简单化。

提高了代码的重用性。

易于维护和功能扩充。

有利于团队的开发。

 

黑箱测试和白箱测试的区别?

黑箱测试即功能测试或数据驱动测试,它是在已知产品所具有的功能,通过测试来检测每个功能都是否正常使用。在测试时,把程序看作一个不可打开的黑箱子,在完全不考虑程序内部结构和内部特性的情况下,测试者在程序接口进行测试,它只检查程序功能是否按照需求规格说明书的规定正常使用,程序是否能适当地接收输入数据而产生正确的输出信息,并且保证外部信息(如数据库或文件)的完整性。黑箱测试的主要方法有等价类划分,边值分析,因果图,错误推测等,主要用于软件确认测试。黑箱法着眼于程序外部结构,不考虑内部逻辑结构,针对软件界面和软件功能进行测试。黑箱法是穷举输入测试,只有把所有可能的输入都作为测试情况使用,才能以这种方法查出程序中所有的错误。不仅要测试合法的输入还要测试不合法但是可能的输入进行测试。

白箱测试也称结构测试或逻辑驱动测试,它知道内部工作的过程,可通过测试来检测内部动作是否按规格说明书的规定正常进行,按照程序内部的结构测试程序,检验程序中的每条通路是否都能按照预定要求正确工作,而不顾它的功能。白箱测试的主要方法是逻辑驱动,基路测试等,主要用于软件验证。白箱法全面了解程序内的逻辑驱动,对所有逻辑路径进行测试,白箱法是穷举路径测试,在使用这一方案时,测试者必须检查程序的内部结构,从检查程序的逻辑着手,得出测试数据。

 

简述全局变量的优缺点,并说明一个软件项目中,控制全局变量数目的一般策略?

全局变量优点:全局可视,任何一个函数都可以访问和更改其值。内存地址固定,读写效率高。

缺点:使用全局对象的函数依赖于全局对象的存在和类型,这使得在不同的上下文环境中重用该函数变得困难。

如果程序被修改,则全局依赖增加了引入错误的可能性,而且只对局部进行修改也要求程序员理解整个程序。

如果全局对象得到一个不正确的值,则必须检查整个程序判断错误发生的位置。

当一个函数使用全局对象时,递归更加难以正确完成,递归只调用函数自身。

在线程存在的情况下,我们必须做特殊的编码,以便同步各个线程对于全局变量的读写操作。

 

传值机制和引用机制的意义和区别?

传值机制中,被调函数的形式参数作为被调函数的局部变量处理,即在堆栈中开辟新的内存空间以存放主调函数放进来的实参的值,从而成为实参的一个副本。值传递的特点是被掉函数对形式参数的任何操作都不会改变主调函数的实参变量的值。

引用机制中,被调函数的形式参数虽然也作为局部变量在堆栈中开辟了内存空间,但是这时存放的是主调函数放进来的实参的地址,被调函数对形参的任何操作都被处理成间接寻址,即通过堆栈中存放的地址访问主调函数中的实参变量。正是因为如此,被调函数对形参做的任何操作都影响了主调函数的实参变量。

区别:所谓值传递,就是说仅将对象的值传递给目标对象,就相当于copy,系统将为目标对象重新开辟一个完全相同的内存空间。

所谓引用,就是说将对象在内存中的地址传递给目标对象,就相当于使目标对象和原始对象对应同一个内存存储空间。此时,如果对目标对象进行修改,内存中的数据也会被修改。

面向对象和面向过程编程的区别?

面向过程就是分析出解决问题的步骤,然后用函数把这些步骤一步一步地实现,使用的时候一个一个依次调用函数就可以了。

面向对象是把构成问题事务分解为各个对象,建立对象的目的不是为了完成一个步骤,而是为了描述某个事务在整个解决问题的步骤中的行为。

总的来时面向对象是高度实物抽象化,而面向过程是自顶向下的编程。

 

简述对象和类之间的关系?

类是对象,事物的描述和抽象,是具有相同属性和行为的对象集合,而对象是类的具体实例。

类是抽象的,不占用内存,而对象是具体的占用存储空间。类是具有相同属性和行为的一组对象的集合。对象是具体存在的事物,明确定义状态和行为。

类是用于创建对象的蓝图,它是一个定义包括在特定类型的对象中的方法和变量的软件模板

 

 

在人类自然语言中,一个动词常具有不同的含义。在面向对象程序设计语言中,也可以表达这种现象。请指出面向对象程序设计中表达这种现象的两种常用方式。

多态:在面向对象语言中,接口的多种不同的实现方式即为多态。同一操作作用于不同的对象,可以有不同的解释,产生不同的结果。在运行时,可以通过指向基类的指针来调用实现派生类中的方法。把不同的子类对象都当作父类来看,可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,以适应需求的不断变化。赋值之后,父类型的引用就可以根据当前赋值给它的子对象的特性以不同的方式运作。

重载:重载是在同一个类中两个或两个以上的方法,拥有相同的方法名,但是参数却不相同,方法体也不相同,就是在类中可以创建多个方法,他们具有相同的名字,但具有不同的参数和不同的定义,调用方法时通过传递给它们的不同参数个数和参数类型,来决定具体使用哪个方法。

简述你对软件通用性的理解,哪些手段可以提高通用性

 

简述内存的动态分配和静态分配的区别

时间不同,静态分配发生在程序编译和连接的时候,需要预先设置存储空间的大小。动态分配则发生在程序调入和执行的时候,在程序执行过程中动态地分配或者回收存储空间的大小,由系统根据程序的需要进行内存分配。

空间不同,堆都是动态分配的。栈用静态分配和动态分配两种,静态分配是编译器完成的,比如局部变量的分配。动态分配是由函数molloc进行分配。不过栈的动态分配和堆不同,它的动态分配是由编译器进行释放,无需手工实现。

列举三种排序方法,简要比较他们的优缺点和时间复杂度?

冒泡排序:简单易实现,稳定,占用空间少,最好的情况下能达到O(n);每次都需要两两元素进行比较,且只能移动相邻的两个元素,慢,O(n2)

快速排序:平均排序速度最快O(nlogn),数据移动少,但序列有序时最慢,变为O(n2),不稳定.

插入排序:数据基本有序时快,稳定占用空间少,比较次数不一定,比较次数越少,插入点后的数据移动越多,特别是数据总量庞大时。

 

  • 7
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值