C++基础知识概念(二)

C++基础知识概念(二)

26 析构函数带 virtual 和 不带 virtual 的区别
如果基类要被派生,则析构函数一定要带 virtual。否则,通过基类指针指向派生类对象 后,删除该指针时并不会释放派生类对象的空间。也就是不会调用派生类的析构函数。
如果打算允许其他人通过基类指针调用对象的析构函数,就需要让基类的析构函数称为虚函数,否则执行delete的结果是不正确的。

不带 virtual 的几种情况
作为非公有基类
不作为接口使用的基类
可以保证这个类不被 public 继承
如果他的所有派生类的 virtual 函数都是什么都不做
如果不需要基类指针指向派生类对象

27 重写、重载和隐藏的区别?

重载:在一个类中的同名函数,但参数列表不同,函数的返回值相同。
隐藏:派生类的函数屏蔽了与其同名的父类函数
重写(覆盖):父类和子类存在相同的函数,包括返回值,参数列表均相同,父类的该 函数必须含有 virtual 关键字。

28 C++中的四个默认的函数
构造函数:先基类后派生类
拷贝函数:对象被创建时调用
调用拷贝构造函数的情况:
a) 一个对象以值传递的方式传入函数体
b) 一个对象以值传递的方式从函数返回
c) 一个对象需要通过另外一个对象初始化
析构函数:每个类只有一个析构函数,
赋值函数:

29 不可以被重载的运算符–五个
类属关系运算符.、成员指针运算符.*、作用域运算符::、 sizeof 运算符和三目运算符?:

30 三种字符数组初始化的方法
char str[5] = {“hello”};
char str[6] = {‘a’,‘b’,‘c’,‘d’,‘e’,’\0’};
char str[] = “abcde”;

31 哪些操作符必须重载为成员函数
必须重载:
= -> () []

32 什么是“else 摇摆问题”,举例说明
C++编译器总是把 else 同与它最近的 if 联系起来,因此如果没有正确放置花括号对就 会出现逻辑错误。

33 函数模板和函数重载的区别与联系
• 函数重载:C++允许使用同一个函数名,不同的参数个数和参数类型来定义多个函数。 重载函数的参数个数、类型、顺序至少有一个不同。返回值可以相同,也可以不同。
• 函数模板:是对一类同构函数的抽象定义,并不是具体的函数,函数模板的定义被编译时不会产生任何可执行的代码。 联系: 针对不同类型的数据,但实现相同功能的函数重载可以通过函数模板来替代。

34 怎样区别虚函数和纯虚函数?两者都有什么作用
纯虚函数是在基类中声明的虚函数,在基类中没有定义。在基类中实现纯虚函数的方法是在函数原型后加“=0。虚函数可以实现也可以不实现。
定义纯虚函数是为了实现一个接口,起到了一个规范的作用。规范继承这个类的程序员必须实现这个接口
声明了纯虚函数的类为抽象类,不能实例化对象。 定义虚函数是为了允许用基类的指针来调用子类的这个函数。
抽象类的作用:将有关的操作作为一个接口组织在一个继承层次结构中,由他来为派生类提供一个公共的根。派生类将具体实现在其基类中作为接口的操作。

35 面向对象程序“接口与实现方法分离”,有什么作用(好处)
接口与实现分离技术可以只把接口暴露给用户,具体的实现细节隐藏起来,当需要改动代码时,只要在实现部分修改后编译,用户无需再编译自己的项目。

36 列出所有与字符串处理有关的头文件
string.h 是 C 语言中字符串操作函数的头文件
cstring 是 c++对 C 语言中的 strcpy 之类的函数申明,包含 cstring 之后,就可以在程序 中使用 C 语言风格的 strcpy 之类的函数。
string 是 c++语言中 string 类模板的申明
cstring 是 MFC 中定义的字符串类,MFC 中很多类及函数都是以 cstring 为参数的
cctype中是C风格字符分类的一些函数
sstream中是C++字符串流的相关函数

37 C++中显示类型转换
static_cast:最常用的类型转换,提供基本数据类型之间的转换操作。
const_cast:可以把 const 类型的指针转换为非 const 类型的指针。
reinterpret_cast:解释的意思,主要用于不相关类型之间的转换。目标和原始值之 间至少有相同的位数,我们可以将转换之后的值再转换回去,而不像其它 3 种类型 可能会导致精度丢失
dynamic_cast:运行时检查该转换是否类型安全,但只有在多态类型时合法,主要 用于类层次间的上行和下行转换,还可以用于类之间的交叉转换。在进行类层次间 的上行转换时和 static_cast 效果一样,进行下行转换时,具有类型检查的功能,比 static_cast 更安全。

38 delete 和 delete [] 的区别?
delete ptr 代表用来释放内存,且只用来释放 ptr 指向的内存。
delete[] rg 用来释放 rg 指向的内存!!还逐一调用数组中每个对象的析构函数 对于像 int/char/long/int*/struct 等等简单数据类型,由于对象没有 destructor,所以用 delete 和 delete [] 是一样的!但是如果是 C++对象数组就不同了!

39 存储类别说明符可划分为两类。
静态存储类别(static,extern)和自动存储类别(auto, register)。这样的变量在程序执行进入到定义它们的程序块时创建,在程序块激活时存在, 在程序块退出时销毁。

40 什么是运算符重载,它如何增强 C++的扩展性?
运算符重载是对已有的运算符赋予多重含义,使得同一个运算符作用于不同类型的数据时导致不同的行为。 运算符重载的本质是函数重载,可以改变现有运算符的操作方式,以适用于类类型,为类的用户提供了一个直接的接口,使得用户程序所用的语言是面向问题的,而不是面向机器的,增强了 C++的扩展性。

41 为什么说”继承是 C++面向对象的主要特征之一”?请简要说明?
继承是一种联结类的层次模型,层次结构的上层是最具有通用性的,而下层的部分,即后代具有特殊性。类可以从他的祖先那里继承方法和成员变量,也可以增加新的方法是适用 于特殊的需要。如果没有继承,类就缺失了一块层次结构,代码重用和数据共享就贯彻不到底,有了继承,就会有抽象编程中的多态问题,只有从机制内部真正解决了多态表现问题, 对象的数据封装,信息隐藏,代码重用等招式才能淋漓尽致的发挥出来。才称得上真正的面向对象编程。

42 作用域辨析有哪些?
类作用域: 在类的作用域内,类的成员可以被类的所有成员函数直接访问,在类的作用域之外, public 类成员通过对象的句柄之一而引用。句柄可以是对象名称、对象的引用、对象的指针。 对象、引用或指针指定了客户可访问的接口。
全局名字空间作用域: 声明与任何函数或者类之外的标识符具有全局名字空间作用域,这种标识符对于从其声 明处开始直到文件结尾处为止出现的所有函数都是已知的,即可访问的。位于函数之外的全局变量。函数定义和函数原型都属于该作用域。
函数作用域: 标签是唯一具有函数作用域的标识符,标签可以在函数中的任何地方使用,但是不能在 函数体外被引用,一般用于switch语句和goto语句。
局部作用域: 在一个语句块中声明的作用域,开始于标识符的声明出,结束于标识符声明处所在语句 块的结束右花括号处。局部变量具有局部作用域,函数形参也是函数的局部作用域。当语句 块是嵌套的,并且外层语句块的一个标识符和内层语句块的一个标识符具有相同的名字时, 外层的标识符处于隐藏状态,直到内存的语句块执行结束为止。
函数原型作用域: 函数原型形参列表中的标识符,在一个函数原型中,一个特定的标识符只能使用一次。

43 STL 是什么?组成部分和区别。
STL 是 c++提供的标准模板库
STL 的主要组成部分为:容器、迭代器、算法、函数对象和适配器。其中算法处于核心地位,迭代器如同算法和容器之间的桥梁,算法通过迭代器从容器中获取元素,然后将获取的元素传递给特定的函数对象的操作,最后将处理后的结果存储到容器中。

44 如何声明和使用虚函数。说明它在多态性中的作用和意义。
• 声明:在基类中声明成员函数时在前面加上关键字 virtual 。
• 使用虚函数:在基类中将成员函数声明为虚函数,这样在派生类中重写该方法后,在使用基类的指针或引用指向派生类对象时,就可以通过这个基类指针或引用访问到派生类的方法。

C++中的多态可分为四类:重载多态、强制多态、包含多态和参数多态,其中包含多态是研究类族中定义于不同类中的同名函数的多态行为,主要通过虚函数来实现。多态使得接 口与实现得到分离,要利用统一接口实现运行时多态一般需要动态绑定,而虚函数是动态绑定的基础,就使得虚函数在多态中很重要。

多态指同样的消息被不同类型的对象接收时导致不同的行为。 虚函数机理:当编译器看到 fn 的虚函数标志时,会记下,等遇到这个虚函数的调用时,将该捆绑操作滞后到运行中,以实际的对象来捆绑其对应的成员函数操作,编译器在捆绑操作 b.fn()处避开函数调用,只作一个指向实际对象成员函数的间接访问,每个实际的对象都需 额外占有一个指针空间,以指向类中的虚函数表。

45 什么是逻辑错误?什么是语法错误?请举例说明。
逻辑错误:由于程序设计人员设计的算法有错或编写的程序有错,此时程序一般能够正 常运行,但是通知给系统的指令与解题的原意不相同,即出现了逻辑上的混乱。 例如:int a[5] = { 1 , 2 , 3 , 4 , 5} ; for( int i = 0 ; i <= 0 ; i ++ ) cout << a[i] << endl ; //发生数组越界
语法错误:违背了 C++语言的规定,不能生成可执行文件,主要是语句的结构或拼写中 存在的错误。 例如:for( int i = 0 , i < 10 , i ++) { } //应该用“;

46 编写语句说明枚举类型是如何定义和使用的。
枚举类型的声明形式如下 enum 枚举类型名 { 变量值列表 } ;
例如: enum weekday{ sun , mon , tue , wed , thu , fri , sta } ; 变量定义:enum weekday a , b , c = tue ; //也可以省略 enum

枚举元素具有默认值,他们依次是:0 , 1 , 2 , … , 例子中:sun 的值为 0 , mon 的值 为 1,tue 的值为 2,… ,sta 的值为 6 。
枚举元素按常量处理,不能进行赋值。
整数值也不能赋给枚举变量,如确实需要可进行强制类型转换。
枚举变量可以进行关系运算。

47 ADT是什么?简述你对“数据抽象”和“信息隐藏”的认识。
C++内部的数据类型包括基本类型复合类型(数组、字符串、指针和结构),有表示范围,只是用可以接受的方式表示实际概念。确定了一个类型就确定了计算机存储给类型所 需要的容量,确定了其表示范围,也确定了对该类型可以进行的操作。
抽象数据类型(Abstract Data Type),简称 ADT,是指一个数学模型以及定义在该模型 上的一组操作。 通常以以下格式定义: ADT 抽象数据类型名{ 数据对象:<数据对象的定义> 数据关系:<数据关系的定义> 基本操作:<基本操作的定义> }

数据抽象:对具体事物描述的一个概括。通过数据抽象可以将数据类型的定义和它的实现分开,使得只研究和使用它的结构而不用考虑它的实现细节成为可能。C++中的类就是一种数据抽象,类是具有相同属性和服务的一组对象的集合。

信息隐藏:C++中的封装就是信息隐藏的一种,即尽可能的隐藏对象的内部细节,对外形成一个边界,只保留有限的对外接口使之与外部反生关系。

48 简述你对“面向对象”和“面向过程”编程思想的理解和认识。

“面向过程”是一种以事件为中心的编程思想,就是分析出解决问题所需要的步骤,然后 用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。过程化编程强调 功能,以过程模块为中心,分层逐步展开设计。通常采用结构化程序设计,基本思路为:自 顶向下、逐步求精。

“面向对象”的编程思想就是把你需要解决的问题中的所有具体的东西,都看成一个个具 有属性和行为的对象,然后把所有具有相同性质的对象抽象成类,那些与问题无关的对象则 忽略。对象化编程强调分离抽象层次,以便让程序员分工,关心不同抽象层次中的细节,而 不用去关心不同抽象层次的联系,数据安全而隐蔽,不同抽象层次的职责分明。

49 写出递归函数定义以及相应的优缺点
递归函数是直接或间接地(通过另一个函数)调用自己。

优点:结构清晰,可读性强,使程序易于理解和调试。
缺点:效率较低。递归是有时间和空间消耗的。另外,递归有可能很多计算都是重复的,从而给性能带来很大的负面影响。因为递归的本质是把一个问题分解成连个或者多个小问题。如果多个小问题存在相互重叠的部分,那么就存在重复的计算。
可能导致调用栈溢出。每一次函数调用在内存栈中分配空间,而每个进程的栈的容量是有限的。当递归调用的层级太多时,就会超出栈的容量,从而导致栈溢出。

50 写出包含输入输出的标准库

fstream、iomanip、ios、iosfwd、iostream、ostream、istream、sstream、streambuf

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值