1. Final关键字 -
C++11新特性:防止继承类(不希望其他类继承它),在类名后跟一个final
class Last final { /* */ };
2. Class和struct的区别 -
C++和C的角度:
C++中的struct和class区别不是很大,两者有很大的相似性,为什么C++要保留struct,是因为C++是向下兼容的,C++保留了C的很多东西。
struct在C中是一种数据类型,不能定义函数,否则编译器报错!
在面向对象的编程中,数据和数据操作是分开的。而当struct进入面向对象的C++时,在struct中定义函数能运行,C++认为数据和数据操作是一个整体,不应该分开,这就是struct在C和C++两个时代的差别。
在C++中struct有很大的扩充:
1. struct可以包括成员函数
2. struct可以实现继承
3. struct可以实现多态
权限不同:
struct:不加修饰符默认定义为public,默认公有继承(public)
class:不加修饰符默认定义为private,默认私有继承(private)
struct可以继承class,class也可继承struct,权限取决于子类。
统一代码风格:希望成员是public选择struct,反之亦然
其他:
- class用于定义模板参数(“typename”),但struct不用于定义模板参数。
- class和struct如果定义了构造函数,都不能用大括号初始化
- 如果没有定义构造函数,struct可以用大括号初始化
- 如果没有定义构造函数且所有成员变量都是public,class可以用大括号初始化。
两者最大的区别在思想:
C语言编程单位是函数,语句是程序的基本单元
C++语言编程单位是类
C到C++的设计有过程设计为中心向以数据组织为中心转移。
3. 不可继承的基类 -
定义类时在类名后面加上final
class NoDerived final { };
4. 不可实现的类 -
定义成抽象类
- 含有 (或者未经覆盖直接继承)纯虚函数的类是抽象基类,抽象基类负责定义接口,而后续的其他类可以覆盖该接口
- 不能定义一个抽象基类对象
//基类
class A{
public:
virtual void fun() = 0;
virtual void fun1() const = 0;
};
//子类 (c++11)
class B:public A{
public:
void fun() override;
void fun1() const override;
};
5. 不可重写的函数 -
在函数形参后面加上final,void fun() final
表示不允许后续的其他类覆盖fun
6. 多态 +
oop(面向对象编程)的核心思想是多态性。把具有继承关系的多个类型成为多态类型。引用或指针的静态类型与动态类型不同这一事实是C++语言支持多态性的根本所在。
- 使用基类的引用或指针调用基类中定义的一个函数时,我们不知道该函数真正的对象是什么类型,可能是一个基类对象也可能是派生类对象。如果函数是虚函数,则直到运行时才会决定执行哪个版本,判断的依据是引用或指针所绑定的对象的真实类型。对非虚函数的调用在编译时进行绑定。
- 通过对象进行的函数(虚函数或非虚函数)调用也在编译时绑定。对象的类型是确定不变的,通过对象进行的函数调用将在编译时绑定到该对象所属类中的函数版本上。
- 当且仅当通过指针或引用调用虚函数时,才会在运行时解析该调用,也只有在这种情况下对象的动态类型才有可能与静态类型不同。
7. 静态多态 -
在程序编译时就绑定函数地址,动态多态是在程序运行时绑定。
8. 返回值与多态关系 -
多态的实现是根据函数名字和参数绑定到不同的函数执行,跟返回值没有关系。
9. 指针 +
10. 野指针 ±
野指针指向了一块随机内存空间,不受程序控制,如果指针指向已经被删除的对象或者指向一块没有访问权限的内存空间,之后如果对其再引用会出问题。
(1)指针定义时未被初始化:指针在被定义时,若没有初始化会指向随机区域,除static修饰的指针外在被定义时是不会被置为空的,默认随机。
(2)指针被释放时没有置空:malloc开辟内存空间时,检查返回值是否为空,如果为空则开辟失败;不为空则指针指向开辟内存的首地址。指针指向的内存在free() /delete释放后,若没有将指针置空或其他赋值,就会使其成为一个野指针。
(3)指针操作超越变量作用域:不要返回指向栈内存的指针或引用,因为栈内存在函数结束的时候会被释放。
野指针危害:
野指针的问题在于,指针指向的内存已经无效了,而指针没有被置空,解引用一个非空的无效指针是一个未被定义的行为,也就是说不一定导致段错误,野指针很难定位到是哪里出现的问题,在哪里这个指针就失效了,不好查找出错的原因。所以调试起来会很麻烦,有时候会需要很长的时间。
避免方法
- 初始化指针时将其置为NULL,之后再对其进行操作。
- 释放指针时将其置为NULL,最好在编写代码时将free()函数封装一下,在调用free()后就将指针置为NULL
要想彻底地避免野指针,最好的办法就是养成一个良好的编程习惯。
野指针参考
11. 数组链表 +
答了存储方式,增删查改用链表方便,查找用数组等等。
12. Inline关键字 ±
Lnline关键字实现内联函数:
(1) 函数调用会降低程序的执行效率,增加时间和空间的开销,因此对于一些简单、规模较小又使用频繁的函数,可以设计为内联函数
(2)内联函数不是在调用时发生控制转移,而是在编译时将函数体嵌入在每一个调用处,节省了参数传递、控制转移等开销
(3)语法:
Inline 类型说明符 函数名(含类型说明的形参表)
//内联函数计算面积
inline double calArea(double radius){
return PI*radius*radius;
}
(4)在类中写在内部的函数可能会被编译成内联函数,如果一个复杂的函数定义为内联函数,会造成代码膨胀,增大开销,编译器会转换为其他函数处理(inline不承诺修饰函数为内联函数)
13. STL库有哪些了解
说了vector 、set、 map
14. Map内部是什么实现-
红黑树。
红黑树概念:
15. Map键值对有哪些注意事项-
16. 手撕代码 -
链表相加:
L1:1->6->3 361
L2:2->3->4 432
L1+L2 : 793
输出:3->9->7
Struct ListNode{
Int val;
ListNode *next;
}
17. New关键字 -
语法:int a = new int a ;
18.为什么空类大小是1
空类也进行实例化,每个实例在内存中都有一个独一无二的地址,为了达到这个目的,编译器会给一个空类隐含加一个字节,这样空类实例化后得到独一无二的地址。
- 补充sizeof类大小知识:sizeof得到的结果为各个非静态数据成员(不包括成员函数)的总和加上编译器额外增加的字节。后者依赖于不同的编译器实现,C++标准对此不作任何保证。
- 一个类中的成员函数、虚函数(虚表占一个地址)、静态数据成员都是不占用类的存储空间的。
很多都没答上来,挂了