1.局部静态变量
这个局部静态变量产生后如果局部函数已经结束,他并不会因为函数的消亡而消亡,而是存储在内存中,不可访问,下次找到这个函数,就会又启用这个变量。
2.指针怎么用,用来干什么
指针可以让函数修改函数的外部变量,引用也可以,具体例子如下:
引用:
3.explicit
就是说,在类中函数传递的过程中,会出现一种特殊情况,那就是,定义类,其实在某种程度上是定义了一种数据类型,但是他的创建是用我们已知的数据类型组合而成的,如果组合的时候,已知的数据类型只有一个,比如说,Myclass(int x)理论上,我们使用函数的时候,直接把int类型带进去也可以计算的,因为在编译器中,他针对这种单变量的class或者是多变量,但是有默认值的class进行了隐式转换,让你能使用了。这种所谓的方便,不一定能起到真正的方便,在后续的代码中可能会出现一些奇奇怪怪的报错,所以在定义这个类的时候,我们就需要用explicit关键词来定义class这样就能让编译器知道不要在后台进行隐式转换,老老实实给我好好编译。下面这个例子:
这个代码,系统会自动给你把2.2转换成2,
4.cast,主要用于类型转换
(1)const_cast:用于移除或添加const性质,唯一可以改变对象const性质的cast
(2)static_cast:用于进行明确定义的类型转换,最安全,只允许在编译期间已知且明确的转换,也可用于子类和父类的替换
(3)dynamic_cast:用于动态类型转换,只能用于多态的类,仅用于指针或引用的转换,或者类中向上或向下的转换。
(4)reinterpret_cast:暴力转换,尽量避免
C++中的类型转换的优点:
(1)有安全检查,安全
(2)转换意图明显,可以直接从代码看出来在干嘛
5.mutable关键字
被mutable修饰的变量将永远处于可变状态
6.const 关键字用来修饰函数的返回值
可以防止修改返回的对象,但是你在使用这个函数的时候,对于变量的定义也需要const定义例如
给返回值加上 const 修饰有以下好处:
避免误修改:如果函数返回了一个指向某个不可修改的字符串的指针,加上 const 限制可以防止调用者意外地修改该字符串。
增强安全性:限制了调用者对返回数据的操作,可以更好地控制数据的使用。
例如,返回一个常量字符串时加上 const 是一种良好的编程习惯。
7.static对象既不属于栈也不属于堆
Non-Local Static对象在main()之前初始化
局部static从函数开始初始化,函数析构以后存起来,不在栈上存储
8.C++中栈和堆的理解
栈用于自动管理局部变量,效率高但空间有限。容易栈溢出
堆用于动态内存分配,适合大型数据结构,但需要手动管理内存,容易发生内存泄漏。
以下是内存泄漏
9.STL(Standard Template Library)
STL对于C++来说就像一个高级库一样,相当于Python中的numpy,有很多的模板,操作,都是给你准备好的,学会使用这些,对C++的数组操作就会有很好的掌控和认知。
(1)容器
也就是C++里的数据结构,就比如set,map,stack,二叉树,链表之类的,存放数据的容器就被称为容器
具有代表性的
(2)算法
提供了诸如排序、搜索、合并、遍历、复制等功能。algorithm 头文件中包含大量常用算法。
(3)迭代器
迭代器是 STL 中用于遍历容器元素的对象,是访问容器的抽象方式。它们封装了指针操作,使容器的内容可以被顺序访问。常见的迭代器类型包括:
输入迭代器
输出迭代器
前向迭代器
双向迭代器
随机访问迭代器
(4)仿函数(函数对象)
通过重载 operator() 操作符的类,它允许将对象当作函数来调用。STL 中很多算法都支持仿函数来提供自定义行为。
(5)适配器
适配器是用来修改其他组件接口的 STL 组件。适配器可以作用于容器、迭代器和函数对象,目的是使这些组件更易用或适应特定需求。
容器适配器:如 stack、queue、priority_queue 是对顺序容器的封装。
迭代器适配器:如 reverse_iterator 提供反向遍历容器的功能。
函数适配器:如 std::bind 将多参数的函数转化为单参数的函数对象。
(6)内存配置器(Allocator)
内存配置器是 STL 中用于管理内存分配的机制。STL 的容器通常使用内置的默认配置器来进行内存管理。配置器通过封装 new 和 delete,提供内存的分配和释放功能。
10.private和protected还有public有什么区别,struct和class的区别
C语言和C++的最大区别就是是否面向对象编程,也就是说C和C++的最大区别就在于,struct和class的区别,struct的继承默认所有成员都是public的,class的继承默认成员是private的,那这个是什么意思呢
private就给了class一种封装,在class内部的函数中,你可以去访问他,但是如果脱离了这个类,在外部实例化然后调用函数的时候,你根本找不到这个函数,这个函数就隐藏掉了,只能在类内访问,所以面向对象编程的习惯就是说,要把除了对外展示的接口之外,全部都变成private封装起来。这就体现了封装的思想。
然后protect是干嘛的,那就是说,在外部实例化的时候,还是不能访问的,但是你在子类继承的时候,你可以通过public访问父类的private,可以重写protect,最外部实例化的时候还是不能访问protect,可以通过public去间接访问。
11.初始化成员列表
在C++中,初始化成员列表是一种在构造函数中初始化类成员的方式,主要是在构造函数的定义中使用冒号 : 之后的一系列初始化列表来直接初始化类的成员。这种初始化方式在某些情况下是必须的。下面是对几种情况的解释:
(1)类的成员是常量成员(const成员)
如果一个类的成员是const,它的值必须在对象创建时初始化,而且一旦初始化后就不能再改变。因此,const成员只能通过初始化列表进行初始化,不能在构造函数内部赋值。
(2)类的成员是对象成员,而该对象没有无参构造函数
当一个类包含了另一个类的对象作为成员,而这个成员对象没有默认的无参构造函数时,必须使用初始化列表来调用该对象的有参构造函数进行初始化。
(3)类的成员是引用(&)
在C++中,引用类型必须在创建时初始化,且一旦初始化后,引用不能再指向其他对象。因为不能在构造函数内部为引用成员赋值,所以必须通过初始化列表进行初始化。
12.没懂:静态函数存在的意义?
静态私有成员在类外不能被访问,可通过类的静态成员函数来访问;
当类的构造函数是私有的时,不像普通类那样实例化自己,只能通过静态成员函数来调用构
造函数。
构造函数就是python里的__init__
对静态成员的理解,就是说,别的函数,他实例化了才真正的存在,但是静态成员是一直存在的,也就是说他只要定义了这个类,那么就有他的存在,每一个对象都可以使用这个静态成员,但是你使用他的时候只能用静态函数访问它。也就是说:
静态成员在类级别上存在,而不是在对象级别上。以下是关键点:
(1)静态成员的共享性:静态成员属于类本身,而不是属于某个具体的对象。所以无论创建多少个对象,静态成员只有一份,并且所有对象共享这一份。
(2)访问静态成员:由于静态成员不属于对象,通常通过类名来访问它(如 ClassName::staticMember)。如果在类内部的静态函数中,也可以直接访问静态成员。非静态成员则需要通过实例化对象来访问。
(3)静态成员函数:静态成员函数可以访问静态成员变量,但不能访问非静态成员变量,因为它不依赖于具体的对象实例。
13.在类外有什么办法可以访问类的非公有成员?
答:友元,继承,公有成员函数。
这个就是三种例子,友元,继承和公有成员函数,其实继承和公有成员函数有点像的。
14.抽象类
不用来定义对象,只用作一种基本类型用来继承,懂了公蜂是吧。
15.运算符重载的意义
在 C++ 中,内置数据类型如 int、float 等,允许我们使用各种运算符(如 +、-、*、/ 等)进行操作。运算符重载就是为了让自定义类的对象也能使用这些运算符,从而提高代码的可读性和易用性。
16.不允许重载的运算符:
.*(成员指针访问运算符号)
2.
::域运算符
3.
Sizeof 长度运算符号
4.
?:条件运算符号
5. .(成员访问符)
17.赋值运算符和拷贝构造函数的区别与联系?
相同点:都是将一个对象 copy 到另一个中去。
不同点:拷贝构造函数涉及到要新建立一个对象。
18.对象间是怎样实现数据的共享的?
通过类的静态成员变量来实现对象间的数据共享。
静态成员变量占有自己独立的空间不为某个对象所私有。
19.友元关系:
友元关系有什么特性?
答:单向的,非传递的,不能继承的。
单向的指,在B中指定friend A,也就是A是B的友元,那么A就可以访问B了,但是B不能访问A的private
非传递的就是,A是B的友元,B是C的友元,那么A不是C的友元。
不能继承的就是不能继承。单线联系
20.const char *p 和 char * const p; 的区别
如果 const 位于星号的左侧,则 const 就是用来修饰指针 *p 所指向的变量,即指针指向的值是常量;
如果 const 位于星号的右侧,const 就是修饰指针 p 本身,即指针本身是常量。
21.构造函数和析构函数是否可以被重载,为什么?
构造函数可以被重载,析构函数不可以被重载。因为构造函数可以有多个且可以带参数,
而析构函数只能有一个,且不能带参数。
22.回调函数
可以理解为,函数的函数,在触发条件后,把函数作为参数传递进函数,执行函数的时候在函数内执行这个额外的函数
23.抽象类可以有构造函数
抽象类中是可以有构造函数的。虽然抽象类不能被实例化,但是抽象类可以被继承,而继承
自抽象类的派生类在实例化时会调用抽象类的构造函数来初始化基类部分。
24.继承的优缺点。
1、类继承是在编译时刻静态定义的,且可直接使用,
2、类继承可以较方便地改变父类的实现。
缺点:
1、因为继承在编译时刻就定义了,所以无法在运行时刻改变从父类继承的实现
2、父类通常至少定义了子类的部分行为,父类的任何改变都可能影响子类的行为
3、如果继承下来的实现不适合解决新的问题,则父类必须重写或被其他更适合的类替换。
这种依赖关系限制了灵活性并最终限制了复用性。
25.预编译
总是使用不经常改动的大型代码体。
程序由多个模块组成,所有模块都使用一组标准的包含文件和相同的编译选项。在这种情况
下,可以将所有包含文件预编译为一个预编译头。
26.多态的作用?
接口重用,内部实现不一样,但是接口是一样的,目的类似。
27.什么函数不能声明为虚函数?
答:构造函数(constructor)
虚函数是为了实现多态,即通过基类的指针或引用调用派生类的成员函数。而构造函数是在
创建对象时自动调用的,不可能通过基类的指针或引用去调用,因此没有多态的需求。