- 计算机程序设计语言的发展历程
机器语言到与汇编语言->高级语言->面向对象的语言 - 面向对象的编程语言的特点
面向对象的编程语言设计出发点是更直接描述客观世界存在的事物(对象)以及它们之间的关系。面向对象的编程语言将客观事物看作是属性和行为(或称服务)的对下个,通过抽象找出同一类对象的共同属性(静态特征)和行为(动态特征),成为类。
抽象,封装,继承,多态。 - 结构化程序设计方法,它的优点缺点有哪些
自顶而下,逐步求精。按功能划分为若干个基本模块,各模块之间的关系尽可能简单,在功能上相对独立,每一个模块内部都是由顺序,选择和循环组成。模块化实现的具体方法是使用子程序。
优点:便于开发维护
缺点:数据结构改变时,所有相关的处理过程都要进行相应的修改,程序可重用性差。 - 什么是对象?什么是面向对象方法?这些方法有哪些特点?
首先,将数据及对数据的操作方法放在一起,作为一个相互依存,不可分离的整体 ——对象。对同类型对象抽象出其共性,形成类。类中的大多数数据,只能用本类的方法进行处理。类通过一个简单的外部接口与外界发生关系,对象与对象之间进行通信。
特点:程序模块的独立性,数据安全性,程序的可重用性提高。
面向对象的基本概念:对象,类,封装,继承,多态性。 - 什么叫做封装?
把对象的属性和服务结合成一个独立的系统单位,并尽可能隐蔽对象的内部细节。 - 面向对象的软件工程包括那些主要内容
面向对象的分析(OOA)面向对象的设计(OOD)面向对象的编程(OOP)面向对象的测试(OOT)面向对象的软件维护(OOSM) - 计算机内部的信息可分为几类?
数据信息和控制信息 - 什么叫做二进制,二进制有哪些优缺点
基数为2,每位的权是以2为底的幂,逢2进位,基本符号只有0和1
优点:易于物理实现,运算简单,机器可靠性高,通用性强 - 比较原码,反码,补码等几种编码方法
原码:数的绝对值与符号一起编码
反码:正数的正码反码一样,负数反码的符号位与原码相同,其它取反
补码:正数补码与原码相同,负数为该反码最末位+1,补码运算的结果仍为补码 - C++语言有哪些主要特点和优点
兼容C和支持面向对象的方法
补充:C++标识符规则:以字母或是_开始,可以由字母数字和下划线组,区分大小写字母,并且不能是C++关键字
补充:符号常量声明时必须赋初值 - 注释有什么作用,C++有几种注释方法
// 与 /* */,对程序进行解释说明,便于阅读 - 变量与常量区别
常量:程序运行过程中其值始终不可变的量
变量:在程序的执行过程中其值可变化的量 - 变量的存储类型:
auto:采用堆栈方式分配内存空间,其存储空间可以被若干变量多次覆盖使用
register:存放在通用寄存器中
extern:在所有函数和程序段中都可引用
static:在内存中以固定地址存放,在整个程序运行期间都有效 - C++ 基本数据类型
类型名 | 长度(字节) |
---|---|
bool | 1 |
char | 1 |
short | 2 |
int | 4 |
long | 4 |
float | 4 |
double | 8 |
- 运算优先级问题以及混合运算数据类型的转换
- 简单的I/O格式控制 头文件 iomainp
操作符名 | 含义 |
---|---|
dec | 十进制 |
hex | 十六进制 |
oct | 八进制 |
ws | 提取空白符 |
ends | 插入空字符 |
endl | 换行并刷新流 |
setsprecision(int) | 设置浮点数的小数位数 |
setw(int) | 设置域宽 |
- 算法的基本控制结构
顺序结构,选择结构,循环结构 - typedef声明
typedef 已有类型名 新类型名表;
- 枚举类型enum
enum 枚举类型名 {变量值列表};
枚举元素按常量处理,不能赋值,枚举元素具有默认值,依次为0,2,2……,也可以在声明时另行定义枚举元素的值,枚举值可以进行关系运算,整数值不能直接赋值给枚举变量,如有需要,可以强制类型转换。
-
有符号整数和无符号整数在计算机内部如何区分?
有符号整数在计算机是以补码形式存储,最高位为符号位。无符号整数只能是正数,以绝对值形式存在的。 -
C++中的函数是什么?什么是主调函数,什么是被调函数,二者之间有什么关系,如何调用一个函数?
调用其他函数的函数称为主调函数,被其他函数调用的函数称为被调函数。一个函数既可能调用别的函数,也可能被别的函数调用。 -
比较值传递和引用传递的相同点与不同点?
值传递:发生函数调用时,给形参分配内存空间,并用实参来初始化形参的值。一旦形参获得了值便于实参脱离关系,之后无论如何变化,都不会影响实参。是单向传递。
引用传递:声明一个引用时,必须同时进行初始化,使它指向一个已经存在的对象,一旦引用被初始化,它就不能改为指向其他对象。用引用作为形参,在函数调用时发生的参数传递,称为引用传递,对引用的任何操作也会直接作用于实参。 -
什么叫内联函数?它有哪些特点?
内联函数不是在调用时发生控制转移,而是在编译时将函数体嵌入在每一个调用处。节省了参数传递,控制转移等开销。
inline 类型说明符 函数名(含类型说明的形参表){
语句序列
}
- 函数原型中的参数名与函数定义中的参数名以及函数调用中的参数名必须一致吗?
函数在定义是可以预先声明默认的形参值,调用时如果给出实参,则用实参初始化形参。有默认值的形参必须在形参列表的最后。在相同的作用域中,不允许 在同一个函数的多个声明中对同一个参数的默认值 重复定义。 - 调用被重载的函数时,通过什么来区分被调用的是哪个函数?
重载:两个以上的函数,具有相同的函数名,但是形参的个数和类型不同,编译器根据实参和形参的类型及个数的最佳匹配,自动确定调用哪个函数。 - 什么叫做嵌套调用?什么叫做递归?
嵌套调用:函数1调用了函数2,函数2再调用函数3,便形成了函数的嵌套调用。
递归:函数可以直接或是间接调用自身。递归过程有两个阶段:递推,回归。 - 当函数发生递归调用时,同一个局部变量在不同递归深度上可以同时存在不同的取值,这在底层是怎么实现的?
对同一个函数的多次不用调用,编译器会为函数的形参和局部变量分配不同的空间,它们互不影响。
抽象:对具体问题(对象)进行概括,抽出一类对象的公共性质并加以描述的过程。
封装:将抽象得到的数据和行为(或功能)相组合,结合成一个有机整体,也就是将数据与操作数据的函数代码进行有机的结合,形成类,其中的数据和函数都是类的成员。
继承:继承机制允许程序员在保持原有类特性的基础上,进行更具体的,更详细的说明。
多态:一段程序能够处理多种类型对象的能力。C++中有强制多态,重载多态,类型参数化多态,包含多态4种形式来实现。
30. 解释public和private的作用,公有类型成员和私有类型成员有哪些区别?
公有类型(public):公有类型成员定义了类的外部接口。
私有类型(private):私有成员只能被本类的成员函数访问,来自类外部的任何访问都是非法的。
31. protected关键字作用
保护类型成员的性质与私有制成员的性质类似,其区别在于继承过程中对产生的新类影响不同。
32. 构造函数与析构函数有什么作用
C++程序中的初始化和清理工作分别由两个特殊的成员函数完成就是构造函数和析构函数。
构造函数的作用就是在对象被创建时利用特定的值构造对象,将对象初始化为一个特定的状态。构造函数在对象被创建的时候自动被调用。
构造函数是类的成员函数,构造函数的函数名与类名相同,没有返回值,构造函数通常被声明为公有函数。
析构函数完成对象被删除前的清理工作。析构函数是在对象的生存期即将结束的时刻被自动调用的。析构函数不接收任何参数。类名前加~,没有返回值,不接收任何参数,但可以是虚函数。
33. 数据成员可以公有的吗?成员函数可以私有的吗?
都可以。
成员函数具体形式:
返回值类型 类名::函数成员表(参数表){
函数体
}
成员函数可私有,数据成员可公有。
34. 已知class A中有数据成员 int a,如果定义了A的两个对象a1,a2,它们各自的数据成员a的值可以不同吗?
可以。
35. 什么叫做复制构造函数?复制构造函数什么时候被调用?
复制构造函数形参是本类对对象的引用。其作用是使用一个已经存在的对象(由复制构造函数的参数指定),去初始化同类的一个新对象。
复制构造函数被调用:
当用类的一个对象去初始化该类的另一个对象时
如果函数的形参是类的对象,调用函数时,进行形参和实参结合时。
如果函数的返回值是类的对象,函数执行完成返回调用者时。
36. 什么叫做作用域,有哪几种类型的作用域?
作用域是一个标识在程序正文中有效的区域。C++标识符中的作用域有函数原型作用域,局部作用域,类作用域和命名空间作用域。
函数原型作用域:在函数声明时形式参数的作用范围就是函数原型作用域。
局部作用域:函数形参表中形参的作用域,从形参列表中的声明处开始,到整个函数体结束之处为止。函数体内声明的变量作用域从声明处开始,一直到生命所在的块结束的大括号为止。
类作用域:具有命名空间作用域的变量也称为全局变量。
37. 什么叫做可见性,可见性的一般规则是什么?
可见性:标识符的有效范围。程序运行到某一点,能够引用到的标识符,就是该处可见的标识符。
一般规则:
- 标识符要声明在前,引用在后。
- 在同一作用域中,不能声明同名的标识符。
- 在没有相互包含关系的不同的作用域中声明的同名标识符互不影响。
- 如果在两个或多个具有包含关系的作用域中声明了同名标识符,则外层标识符在内层不可见。
以上。
38. 什么叫做静态数据成员,有何特点?
在每个类中只有一个副本。
39. 什么叫做静态函数成员,有何特点?
使用 static 关键字声明的函数成员。静态成员函数可以直接访问该类的静态数据和函数和成员。而访问非静态成员,必须通过对象名。
40. 什么叫做友元函数,什么叫做友元类?
友元关系提供了不同类或对象的成员函数之间,类的成员数与一般函数之间进行数据共享机制。
友元函数是在类中用关键字friend修饰的非成员函数,它在函数体中可以通过对象名访问类的私有和保护成员。
若A类为B类的友元类,则A类的所有成员函数都是B类的友元函数,都可以访问B类的私有和保护成员。
注意事项:友元关系不能传递,友元关系是单向的,友元关系不能被继承。
42. 静态成员变量可以是私有的吗,声明一个私有的静态整型成员变量。
private:
static int a;
补充:
使用数组名传递数据时,传递的是地址。
C++中专门用来存放内存单元地址的变量类型,这就是指针类型。
数组名实际上就是一个不能被赋值的指针,即指针常量。
void 类型的指针可以存储任何类型的对象地址。
0专用于标识空指针,也就是一个不指向任何有效地址的指针。 空指针也可以用NULL表示。
函数指针就是专门用来存放函数代码首地址的变量。
一旦函数指针指向了某个函数,它与函数名便有相同的作用。
this指针是一个隐含于每一个类的非静态成员函数中的特殊指针(包括构造函数和析构函数),它用于指向正在被成员函数操作的对象。
指向类的非静态成员的指针:
类型说明符 类名 : : * 指针名;
类型说明符 (类名 : : * 指针名)(参数表);
指针名 = & 类名: : 数据成员名;
动态内存分配: new 数据类型(初始化参数列表) 在程序运行过程中申请分配用于存放定类型数据的内存空间,并根据初始化参数列表中的值进行初始化。如果成功,返回一个指针。
运算符delete 用来删除由new建立的对象,释放市镇所指向的内存空间。格式:delete 指针名;
由new分配的内存必须用delete加以释放,否则会导致动态分配的内存无法回收,使得内存占据的内存越来越大,这叫做“内存泄漏”
如果是new建立的数组,用delete删除时在指针名前面要加” [ ] "
浅复制:可能有两个指针指向同一地址,表面上好像完成了复制,但是并没有形成真正的副本。此外,浅复制还可能造成内存空间被释放两次,造成运行错误
深复制:编写复制构造函数实现“深复制”避免上述结果。
44. 在函数内部定义的普通局部变量和静态局部变量在功能上有何不同?计算机底层对这类变量做了怎样的不同处理,导致了这种差异?
普通局部变量存放在栈中,静态局部变量存放在静态存储区。
45. 比较类的三种继承方式之间的差别
如果不显式地给出继承方式关键字,默认私有继承。派生新类主要分为三个步骤:吸收基类成员,改造基类成员,添加新的成员。
基类的成员可以有 public ,protected, private三种访问属性。基类的自身成员可以对基类任何一个其他成进行访问,但是通过基类的对象,只能访问该类的公有成员。
类的继承方式有public,protected,private三种。
公有继承:基类的公有成员和保护成员的访问属性在派生类中不变,而基类的私有成员不可直接访问。
私有继承:基类中的公有成员和保护成员都以私有成员身份出现在派生类中,而基类的私有成员在派生类不可直接访问。
保护继承:基类的公有成员和保护成员都以保护成员的身份出现在派生类中,而基类的私有成员不可直接访问。
46. 派生类构造函数执行的次序是怎样的
(1)调用基类构造函数,调用顺序按照它们被继承时的声明顺序(从左向右)
(2)对派生类新增的成员对象初始化,调用顺序按照它们在类中声明的顺序。
(3)执行派生类的构造函数体中的内容
47. 什么叫虚基类?它有何作用?
将共同基类设置为虚基类,这时从不同的路径继承过来的同名数据成员在内存中就只有一个副本,同一个函数名也只有一个映射。
48. 组合与继承有什么共同点和差异?通过组合生成类与被组合的类之间的逻辑关系是什么,继承呢?
组合和继承的共同点:
继承和组合的使用都可以减少重复代码,同时若类B是类A的内嵌对象,则B类具有A类的全部数据。
不同点:组合是通过在其他类中定义对象来使用类中的方法和属性,不能访问父类的任何接口。而继承则是从父类中得到方法和属性,即可以得到父类的全部接口,并加以调用。
通过组合生成的类和被组合的类之间的逻辑关系:组合生成的类具有被组合类的全部内容,但是并不包括被组合类的全部接口,就是通过被组合的类的对象只能访问组合类的成员函数,但不能直接访问到被组合类的成员函数。
继承类与基类的逻辑关系:即通过派生类的对象不但可以访问派生类的成员函数,也能访问基类的成员函数,派生类是可以完全继承基类的任何内容的包括全部接口。
49. 基类与派生类的对象,指针或引用之间,哪些情况下可以隐含转换,哪些情况下可以显示转换?在涉及多重继承或虚继承的情况下,在转换时会面临哪些新问题?
派生类指针可以隐含转换为基类指针,而基类指针要想转换为派生类指针,则转换一定 要显示地进行。因为从特殊的指针转换到一般的指针是安全的,因此允许隐含转换;
从一般的指针转换到特殊的指针是不安全的,因此只能显示地转换。基类对象一般无法被显式转换为派生类对象。
在多重继承情况下,执行基类指针到派生类指针的显式转换时,有时需要将指针所存储的地址值进行调整后才能得到新指针的值。
但是,如果 A 类型是 B 类型的虚拟基类,虽然 B 类型的指针可以隐含转换为 A 类型,但是 A 类型指针却无法通过 static_case 隐含转换为 B 类型的指针。
50. 什么叫做多态性?在C++中是如何实现多态的?
多态是指同样的消息被不同类型的对象接收时导致不同的行为。所谓消息是指对类的成员函数的调用,不同的行为指不同的实现,也就是调用了不同的函数。
面向对象的多态性分为4类:重载多态,强制多态,包含多态和参数多态。
编译时的多态和运行时的多态。前者在编译时绑定,后者在运行时时绑定。前者称为静态绑定,后者称为动态绑定
51. 什么叫做抽象类?抽象类有何作用?抽象类的派生类是否一定要给出纯虚函数的实现?
抽象类是一种特殊的类,它为一个类族提供统一的操作界面。抽象类是为了抽象和设计的目的建立的。为了通过它多态地使用其中的成员函数。
带有纯虚函数的类是抽象类,抽象类不能实例化
52. 在C++中,能否声明虚构造函数?为什么,能否声明虚析构函数?有何用途?
虚函数声明只能出现在类定义中的函数原型声明中,而不能在成员函数实现的时候。在C++中,不能声明虚构造函数,但是可以声明虚析构函数。虚析构函数没有类型,没有参数,和普通成员函数相比,虚析构函数情况略为简单些。析构函数设置为虚函数之后,在使用指针引用时可以动态绑定,实现运行时的多态,保证使用基类类型的指针就能够调用适当的析构函数针对不同的对象进行清理工作。
54. 什么叫做流?流的提取和插入是指什么?I/O流在C++中起着怎样的作用?
流是一种抽象,它负责在数据的生产者和数据的消费者之间建立联系,并管理数据的流动。一般意义下的读操作在流数据抽象中被称为从(从流中)提取。写操作被称为(从流中)插入。I/O流类库是C++标准库中的一个面向对象的输入输出软件包。
55. cout,cerr,clog有何区别?
cout 是标准输出流。
cerr 是标准错误输出流,没有缓冲,发送给它的内容立即被输出。
clog 类似于cerr ,但是有缓冲,缓冲区满时被输出。
补充:输出宽度 width 或是setw(头文件iomanip)
seekg 设置指针,保留一个指向文件下一个将读数据的位置的内部指针
tellg 成员函数返回当前文件读指针的位置
56. 什么叫做异常?什么叫做异常处理?
异常(exception) 是程序运行过程中发生的事件, 该事件可以中断程序指令的正常执行流程.
57. C++的异常处理机制有何优点?
C++的异常处理机制使得异常的引发和处理不必在同一函数中,这样底层的函数可以着重解决具体问题,而不必过多考虑对异常的处理。上层调用者可以在适当的位置设计对不同类型异常的处理。
58. 异常处理的执行过程?
(1)程序通过正常的顺序执行到达try语句,然后执行try块内的保护段。
(2)如果在保护段执行期间没有引起异常,那么跟在try后的catch子句就不执行。程序从异常被抛掷的try块后跟随的最后一个catch子句后面的语句继续执行下去。
(3)程序执行到一个throw表达式后,一个异常对象会被创建。若异常的抛出点本身在一个try子句内,则该try语句后的catch子句会按顺序检查异常类型是否与声明的类型匹配;若异常抛出点本身不在任何try子句内,或抛出的异常与各个catch子句所声明的类型皆不匹配,则结束当前函数的执行,回到当前函数的调用点,把调用点作为异常的抛出点,然后重复这一过程。此处理继续下去,直到异常成功被一个catch语句捕获。
(4)如果始终未找到与被抛掷异常匹配的catch子句,最终main函数会结束执行,则运行库函数terminate将被自动调用,而函数terminate的默认功能是终止程序。
(5)如果找到了一个匹配的catch 子句,则catch子句后的复合语句会被执行。复合语句执行完毕后,当前的try块(包含try子句和catch子句)即执行完毕。