26 简述指针常量与常量指针的区别
- 指针常量是指定义了一个指针,这个指针的值只能在定义时初始化,其他地方不能改变。常量指针是指定义了一个指针,这个指针指向一个只读的对象,不能通过常量指针来改变这个对象的值。
- 指针常量强调的是指针的不可改变性,而常量指针强调的是指针对其所指对象的不可改变性。
「注意」 :无论是指针常量还是常量指针,其最大的用途就是作为函数的形式参数,保证实参在被调用函数中的不可改变特性。
27 如何避免"野指针"
- 指针变量声明时没有被初始化。解决办法:指针声明时初始化,可以是具体的地址值,也可让它指向NULL。
- 指针p被free或者delete之后,没有置为NULL。解决办法:指针指向的内存空间被释放后指针应该指向NULL。
- 指针操作超越了变量的作用范围。解决办法:在变量的作用域结束前释放掉变量的地址空间并且让指针指向NULL。
28 句柄和指针的区别和联系是什么?
句柄和指针其实是两个截然不同的概念。Windows系统用句柄标记系统资源,隐藏系统的信息。你只要知道有这个东西,然后去调用就行了,它是个32it的uint。指针则标记某个物理内存地址,两者是不同的概念。
29 new/delete与malloc/free的区别是什么
- new能自动计算需要分配的内存空间,而malloc需要手工计算字节数。
int *p = new int[2];
int *q = (int *)malloc(2*sizeof(int));
- new与delete直接带具体类型的指针,malloc和free返回void类型的指针。
- new类型是安全的,而malloc不是。例如int *p = new float[2];就会报错;而int p = malloc(2sizeof(int))编译时编译器就无法指出错误来。
- new一般分为两步:new操作和构造。new操作对应与malloc,但new操作可以重载,可以自定义内存分配策略,不做内存分配,甚至分配到非内存设备上,而malloc不行。
- new调用构造函数,malloc不能;delete调用析构函数,而free不能。
- malloc/free需要库文件stdlib.h的支持,new/delete则不需要!
「注意」 :delete和free被调用后,内存不会立即回收,指针也不会指向空,delete或free仅仅是告诉操作系统,这一块内存被释放了,可以用作其他用途。但是由于没有重新对这块内存进行写操作,所以内存中的变量数值并没有发生变化,出现野指针的情况。因此,释放完内存后,应该讲该指针指向NULL。
30 说一说extern"C"
extern "C"的主要作用就是为了能够正确实现C++代码调用其他C语言代码。加上extern "C"后,会指示编译器这部分代码按C语言(而不是C++)的方式进行编译。由于C++支持函数重载,因此编译器编译函数的过程中会将函数的参数类型也加到编译后的代码中,而不仅仅是函数名;而C语言并不支持函数重载,因此编译C语言代码的函数时不会带上函数的参数类型,一般只包括函数名。
这个功能十分有用处,因为在C++出现以前,很多代码都是C语言写的,而且很底层的库也是C语言写的,为了更好的支持原来的C代码和已经写好的C语言库,需要在C++中尽可能的支持C,而extern "C"就是其中的一个策略。
- C++代码调用C语言代码
- 在C++的头文件中使用
- 在多个人协同开发时,可能有的人比较擅长C语言,而有的人擅长C++,这样的情况下也会有用到
31 请你来说一下C++中struct和class的区别
在C++中,class和struct做类型定义是只有两点区别:
- 默认继承权限不同,class继承默认是private继承,而struct默认是public继承
- class还可用于定义模板参数,像typename,但是关键字struct不能同于定义模板参数 C++保留struct关键字,原因
- 保证与C语言的向下兼容性,C++必须提供一个struct
- C++中的struct定义必须百分百地保证与C语言中的struct的向下兼容性,把C++中的最基本的对象单元规定为class而不是struct,就是为了避免各种兼容性要求的限制
- 对struct定义的扩展使C语言的代码能够更容易的被移植到C++中
32 C++类内可以定义引用数据成员吗?
可以,必须通过成员函数初始化列表初始化。
33 C++中类成员的访问权限
C++通过 public、protected、private 三个关键字来控制成员变量和成员函数的访问权限,它们分别表示公有的、受保护的、私有的,被称为成员访问限定符。在类的内部(定义类的代码内部),无论成员被声明为 public、protected 还是 private,都是可以互相访问的,没有访问权限的限制。在类的外部(定义类的代码之外),只能通过对象访问成员,并且通过对象只能访问 public 属性的成员,不能访问 private、protected 属性的成员
34 什么是右值引用,跟左值又有什么区别?
左值和右值的概念:
- 左值:能取地址,或者具名对象,表达式结束后依然存在的持久对象;
- 右值:不能取地址,匿名对象,表达式结束后就不再存在的临时对象;区别:
- 左值能赋值,右值不能;
- 左值可变,右值不能(仅对基础类型适用,用户自定义类型右值引用可以通过成员函数改变);
35 面向对象的三大特征
- 封装性:将客观事物抽象成类,每个类对自身的数据和方法实行 protection (private , protected , public )。
- 继承性:广义的继承有三种实现形式:实现继承(使用基类的属性和方法而无需额外编码的能力)、可 视继承(子窗体使用父窗体的外观和实现代码)、接口继承(仅使用属性和方法,实现滞后到子类实现)。
- 多态性:是将父类对象设置成为和一个或更多它的子对象相等的技术。用子类对象给父类对象赋值 之后,父类对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。
36 说一说c++中四种cast转换
C++中四种类型转换是:static_cast, dynamic_cast, const_cast, reinterpret_cast
1、const_cast
- 用于将const变量转为非const
2、static_cast
- 用于各种隐式转换,比如非const转const,void*转指针等, static_cast能用于多态向上转化,如果向下转能成功但是不安全,结果未知;
3、dynamic_cast
用于动态类型转换。只能用于含有虚函数的类,用于类层次间的向上和向下转化。只能转指针或引用。向下转化时,如果是非法的***对于指针返回NULL,对于引用抛异常***。要深入了解内部转换的原理。
- 向上转换:指的是子类向基类的转换
- 向下转换:指的是基类向子类的转换
它通过判断在执行到该语句的时候变量的运行时类型和要转换的类型是否相同来判断是否能够进行向下转换。
4、reinterpret_cast
- 几乎什么都可以转,比如将int转指针,可能会出问题,尽量少用;
5、为什么不使用C的强制转换?
- C的强制转换表面上看起来功能强大什么都能转,但是转化不够明确,不能进行错误检查,容易出错。
37 C++的空类有哪些成员函数
- 缺省构造函数。
- 缺省拷贝构造函数。
- 省析构函数。
- 赋值运算符。
- 取址运算符。
- 取址运算符 const 。
「注意」 :有些书上只是简单的介绍了前四个函数。没有提及后面这两个函数。但后面这两个函数也是 空类的默认函数。另外需要注意的是,只有当实际使用这些函数的时候,编译器才会去定义它们。