1. this
指针
this 指针是一个隐含于每一个非静态成员函数中的特殊指针,它指向调用该成员函数的对象的首地址
- 当对一个对象调用成员函数时,编译程序先将对象的地址赋给
this
指针,然后调用成员函数,每次成员函数存取数据成员时,都隐式使用this
指针 this
指针被隐含地声明为:ClassName *const this
,这意味着不能给this
指针赋值this
是个右值,所以不能取this
的地址
2. delete this
- 类的成员函数中可以调用
delete this
,但是在释放后,对象后续调用的方法不能再用到this
指针 delete this
释放了类对象的内存空间,但是内存空间却并不是马上被回收到系统中,此时其中的值是不确定的delete
的本质是为将被释放的内存调用一个或多个析构函数,如果在类的析构函数中调用delete this
,会陷入无限递归,造成栈溢出
3. 一个空类class中有什么?
构造函数、拷贝构造函数、析构函数、赋值运算符重载、取地址操作符重载、被 const
修饰的取地址操作符重载
4. C++
计算一个类的 sizeof
- 一个空的类
sizeof
返回 1,因为一个空类也要实例化,所谓类的实例化就是在内存中分配一块地址 - 类内的普通成员函数不参与
sizeof
的统计,因为sizeof
是针对实例的,而普通成员函数,是针对类体的 - 一个类如果含有虚函数,则这个类中有一个指向虚函数表的指针(虚函数指针),32位程序占4个字节,64位程序占8个字节
- 静态成员不影响类的大小,被编译器放在程序的数据段中
- 普通继承的类sizeof,会得到基类的大小加上派生类自身成员的大小
- 当存在虚拟继承时,派生类中会有一个指向虚基类表的指针。所以其大小应为普通继承的大小,再加上虚基类表的指针大小
5. 构造函数和析构函数能被继承吗?
不能。构造函数和析构函数是用来处理对象的创建和析构的,它们只知道对在它们的特殊层次的对象做什么
6. 构造函数能不能是虚函数?
不能。虚函数对应一个虚函数表,可是这个虚函数表存储在对象的内存空间的。问题就在于,如果构造函数是虚的,就需要通过 虚函数表来调用,可是对象还没有实例化,也就是内存空间还没有,就不会有虚函数表
7. 构造函数和析构函数能不能被重载?
构造函数可以被重载,析构函数不可以被重载。因为构造函数可以有多个且可以带参数, 而析构函数只能有一个,且不能带参数。
8. 构造函数调用顺序,析构函数调用顺序?
基类的构造函数——>成员类对象的构造函数——>派生类的构造函数;
析构函数相反:派生类析构——>成员类对象析构——>基类析构
9. 构造函数和析构函数调用时机
- 全局范围中的对象:构造函数在所有函数调用之前执行,在主函数执行完调用析构函数
- 局部自动对象:建立对象时调用构造函数,函数结束时调用析构函数
- 动态分配的对象:建立对象时调用构造函数,调用释放时调用析构函数
- 静态局部变量对象:建立对象时调用构造函数,在主函数结束时调用析构函数
10. 拷贝构造函数中深拷贝和浅拷贝区别
- 深拷贝会先申请一块和拷贝数据一样大的内存空间,然后将数据逐字节拷贝过去,拷贝后两个指针指向不同的两个内存空间
- 浅拷贝仅是拷贝指针地址,拷贝后两个指针指向同一个内存空间
当浅拷贝时,如果原来的对象调用析构函数释放掉指针所指向的数据,则会产生空悬指针,因为所指向的内存空间已经被释放了
11. 什么时候必须重写拷贝构造函数?
当构造函数涉及到动态内存分配时,要自己写拷贝构造函数,并且要深拷贝
12. 面向过程编程和面向对象编程的区别
- 面向过程:就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现(函数驱动)
- 面向对象:面向对象是一种对现实世界理解和抽象的方法,强调的是通过将需求要素转化为对象进行问题处理的一种思想(对象驱动)
13. 为什么内联函数,构造函数,静态成员函数不能为virtual函数?
- 内联函数:内联函数是在编译时期展开,而虚函数的特性是运行时才动态联编,所以两者矛盾,不能定义内联函数为虚函数
- 构造函数:构造函数用来创建一个新的对象,而虚函数的运行是建立在对象的基础上,在构造函数执行时,对象尚未形成,所以不能将构造函数定义为虚函数
- 静态成员函数:静态成员函数属于一个类而非某一对象,没有this指针,它无法进行对象的判别
- 友元函数:C++不支持友元函数的继承,对于没有继承性的函数没有虚函数